Package org.docx4j.openpackaging

Source Code of org.docx4j.openpackaging.URIHelper

/*
* Copyright (c) 2006, Wygwam
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* - Neither the name of Wygwam nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.docx4j.openpackaging;

import java.net.URI;
import java.net.URISyntaxException;

import org.docx4j.openpackaging.exceptions.InvalidFormatException;
import org.docx4j.openpackaging.parts.PartName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;



/**
* Helper for part and pack URI.
*
* @author Julien Chable, CDubet
* @version 0.3
*/
public final class URIHelper {

  private static Logger log = LoggerFactory.getLogger(URIHelper.class)
 
  /**
   * Package root URI.
   */
  private static URI packageRootUri;

  /**
   * Extension name of a relationship part.
   */
  public static final String RELATIONSHIP_PART_EXTENSION_NAME;

  /**
   * Segment name of a relationship part.
   */
  public static final String RELATIONSHIP_PART_SEGMENT_NAME;

  /**
   * Segment name of the package properties folder.
   */
  public static final String PACKAGE_PROPERTIES_SEGMENT_NAME;

  /**
   * Core package properties art name.
   */
  public static final String PACKAGE_CORE_PROPERTIES_NAME;

  /**
   * Forward slash URI separator.
   */
  public static final char FORWARD_SLASH_CHAR;

  /**
   * Forward slash URI separator.
   */
  public static final String FORWARD_SLASH_STRING;

  /**
   * Package relationships part URI
   */
  public static final URI PACKAGE_RELATIONSHIPS_ROOT_URI;

  /**
   * Package relationships part name.
   */
  public static final PartName PACKAGE_RELATIONSHIPS_ROOT_PART_NAME;

  /**
   * Core properties part URI.
   */
  public static final URI CORE_PROPERTIES_URI;

  /**
   * Core properties partname.
   */
  public static final PartName CORE_PROPERTIES_PART_NAME;

  /**
   * Root package URI.
   */
  public static final URI PACKAGE_ROOT_URI;

  /**
   * Root package part name.
   */
  public static final PartName PACKAGE_ROOT_PART_NAME;

  /* Static initialization */
  static {
    RELATIONSHIP_PART_SEGMENT_NAME = "_rels";
    RELATIONSHIP_PART_EXTENSION_NAME = ".rels";
    FORWARD_SLASH_CHAR = '/';
    FORWARD_SLASH_STRING = "/";
    PACKAGE_PROPERTIES_SEGMENT_NAME = "docProps";
    PACKAGE_CORE_PROPERTIES_NAME = "core.xml";

    // Make URI
    URI uriPACKAGE_ROOT_URI = null;
    URI uriPACKAGE_RELATIONSHIPS_ROOT_URI = null;
    URI uriPACKAGE_PROPERTIES_URI = null;
    try {
      uriPACKAGE_ROOT_URI = new URI("/");
      uriPACKAGE_RELATIONSHIPS_ROOT_URI = new URI(FORWARD_SLASH_CHAR
          + RELATIONSHIP_PART_SEGMENT_NAME + FORWARD_SLASH_CHAR
          + RELATIONSHIP_PART_EXTENSION_NAME);
      packageRootUri = new URI("/");
      uriPACKAGE_PROPERTIES_URI = new URI(FORWARD_SLASH_CHAR
          + PACKAGE_PROPERTIES_SEGMENT_NAME + FORWARD_SLASH_CHAR
          + PACKAGE_CORE_PROPERTIES_NAME);
    } catch (URISyntaxException e) {
      // Should never happen in production as all data are fixed
    }
    PACKAGE_ROOT_URI = uriPACKAGE_ROOT_URI;
    PACKAGE_RELATIONSHIPS_ROOT_URI = uriPACKAGE_RELATIONSHIPS_ROOT_URI;
    CORE_PROPERTIES_URI = uriPACKAGE_PROPERTIES_URI;

    // Make part name from previous URI
    PartName tmpPACKAGE_ROOT_PART_NAME = null;
    PartName tmpPACKAGE_RELATIONSHIPS_ROOT_PART_NAME = null;
    PartName tmpCORE_PROPERTIES_URI = null;
    try {
      tmpPACKAGE_RELATIONSHIPS_ROOT_PART_NAME = createPartName(PACKAGE_RELATIONSHIPS_ROOT_URI);
      tmpCORE_PROPERTIES_URI = createPartName(CORE_PROPERTIES_URI);
      tmpPACKAGE_ROOT_PART_NAME = new PartName(PACKAGE_ROOT_URI,
          false);
    } catch (InvalidFormatException e) {
      // Should never happen in production as all data are fixed
    }
    PACKAGE_RELATIONSHIPS_ROOT_PART_NAME = tmpPACKAGE_RELATIONSHIPS_ROOT_PART_NAME;
    CORE_PROPERTIES_PART_NAME = tmpCORE_PROPERTIES_URI;
    PACKAGE_ROOT_PART_NAME = tmpPACKAGE_ROOT_PART_NAME;
  }

  /**
   * Gets the URI for the package root.
   *
   * @return URI of the package root.
   */
  public static URI getPackageRootUri() {
    return packageRootUri;
  }


  /**
   * Know if the specified URI is a relationship part name.
   *
   * @param partUri
   *            URI to check.
   * @return <i>true</i> if the URI <i>false</i>.
   */
  private static boolean isRelationshipPartURI(URI partUri) {
    if (partUri == null)
      throw new NullPointerException("partUri");

    return partUri.getPath().matches(
        ".*" + RELATIONSHIP_PART_SEGMENT_NAME + ".*"
            + RELATIONSHIP_PART_EXTENSION_NAME + "$");
  }

  /**
   * Get file name from the specified URI.
   */
  public static String getFilename(URI uri) {
    if (uri != null) {
      String path = uri.getPath();
      int len = path.length();
      int num2 = len;
      while (--num2 >= 0) {
        char ch1 = path.charAt(num2);
        if (ch1 == URIHelper.FORWARD_SLASH_CHAR)
          return path.substring(num2 + 1, len);
      }
    }
    return "";
  }

  /**
   * Get the file name without the trailing extension.
   */
  public static String getFilenameWithoutExtension(URI uri) {
    String filename = getFilename(uri);
    int dotIndex = filename.lastIndexOf(".");
    if (dotIndex == -1)
      return filename;
    return filename.substring(0, dotIndex);
  }

  /**
   * Get the directory path from the specified URI.
   */
  public static URI getPath(URI uri) {
    if (uri != null) {
      String path = uri.getPath();
      int len = path.length();
      int num2 = len;
      while (--num2 >= 0) {
        char ch1 = path.charAt(num2);
        if (ch1 == URIHelper.FORWARD_SLASH_CHAR) {
          try {
            return new URI(path.substring(0, num2));
          } catch (URISyntaxException e) {
            return null;
          }
        }
      }
    }
    return null;
  }

  /**
   * Combine two URI.
   *
   * @param prefix
   * @param suffix
   * @return
   */
  public static URI combine(URI prefix, URI suffix) {
    URI retUri = null;
    try {
      retUri = new URI(combine(prefix.getPath(), suffix.getPath()));
    } catch (URISyntaxException e) {
      throw new IllegalArgumentException(
          "Prefix and suffix can't be combined !");
    }
    return retUri;
  }

  /**
   * Combine a string URI with a prefix and a suffix.
   */
  public static String combine(String prefix, String suffix) {
    if (!prefix.endsWith("" + FORWARD_SLASH_CHAR)
        && !suffix.startsWith("" + FORWARD_SLASH_CHAR))
      return prefix + FORWARD_SLASH_CHAR + suffix;
    else if ((!prefix.endsWith("" + FORWARD_SLASH_CHAR)
        && suffix.startsWith("" + FORWARD_SLASH_CHAR) || (prefix
        .endsWith("" + FORWARD_SLASH_CHAR) && !suffix.startsWith(""
        + FORWARD_SLASH_CHAR))))
      return prefix + suffix;
    else
      return "";
  }

  /**
   * Fully relativize the target part URI against the source part URI.
   *
   * @param sourceURI
   *            The source part URI.
   * @param targetURI
   *            The target part URI.
   * @return A fully relativize part name URI ('word/media/image1.gif',
   *         '/word/document.xml' => 'media/image1.gif') else
   *         <code>null</code>.
   */
  public static URI relativizeURI(URI sourceURI, URI targetURI) {
    StringBuilder retVal = new StringBuilder();
    String[] segmentsSource = sourceURI.getPath().split("/", -1);
    String[] segmentsTarget = targetURI.getPath().split("/", -1);

    // If the source URI is empty
    if (segmentsSource.length == 0) {
      throw new IllegalArgumentException(
          "Can't relativize an empty source URI !");
    }

    // If target URI is empty
    if (segmentsTarget.length == 0) {
      throw new IllegalArgumentException(
          "Can't relativize an empty target URI !");
    }
   
    // If the source is the root, then the relativized
    //  form must actually be an absolute URI
    if(sourceURI.toString().equals("/")) {
      return targetURI;
    }


    // Relativize the source URI against the target URI.
    // First up, figure out how many steps along we can go
    // and still have them be the same
    int segmentsTheSame = 0;
    for (int i = 0; i < segmentsSource.length && i < segmentsTarget.length; i++) {
      if (segmentsSource[i].equals(segmentsTarget[i])) {
        // Match so far, good
        segmentsTheSame++;
      } else {
        break;
      }
    }

    // If we didn't have a good match or at least except a first empty element
    if ((segmentsTheSame == 0 || segmentsTheSame == 1) &&
        segmentsSource[0].equals("") && segmentsTarget[0].equals("")) {
      for (int i = 0; i < segmentsSource.length - 2; i++) {
        retVal.append("../");
      }
      for (int i = 0; i < segmentsTarget.length; i++) {
        if (segmentsTarget[i].equals(""))
          continue;
        retVal.append(segmentsTarget[i]);
        if (i != segmentsTarget.length - 1)
          retVal.append("/");
      }

      try {
        return new URI(retVal.toString());
      } catch (Exception e) {
        System.err.println(e);
        return null;
      }
    }

    // Special case for where the two are the same
    if (segmentsTheSame == segmentsSource.length
        && segmentsTheSame == segmentsTarget.length) {
      retVal.append("");
    } else {
      // Matched for so long, but no more

      // Do we need to go up a directory or two from
      // the source to get here?
      // (If it's all the way up, then don't bother!)
      if (segmentsTheSame == 1) {
        retVal.append("/");
      } else {
        for (int j = segmentsTheSame; j < segmentsSource.length - 1; j++) {
          retVal.append("../");
        }
      }

      // Now go from here on down
      for (int j = segmentsTheSame; j < segmentsTarget.length; j++) {
        if (retVal.length() > 0
            && retVal.charAt(retVal.length() - 1) != '/') {
          retVal.append("/");
        }
        retVal.append(segmentsTarget[j]);
      }
    }

    try {
      return new URI(retVal.toString());
    } catch (Exception e) {
      System.err.println(e);
      return null;
    }
  }
 

  /**
   * Resolve a target uri against a source.
   *
   * @param sourcePartUri
   *            The source URI.
   * @param targetUri
   *            The target URI.
   * @return The resolved URI.
   */
  public static URI resolvePartUri(URI sourcePartUri, URI targetUri) {
//    log.info("source: " + sourcePartUri);
//    log.info("target: " + targetUri);
    URI uri;
    if (sourcePartUri == null || sourcePartUri.isAbsolute()) {
      throw new IllegalArgumentException("sourcePartUri");
    }
    if (targetUri == null) {
      log.error("targetUri was null");
      throw new IllegalArgumentException("targetUri");     
    } else if (targetUri.isAbsolute()) {     
      log.error("targetUri " + targetUri.toString() + " is absolute!");
      throw new IllegalArgumentException("targetUri");
    }

    uri = sourcePartUri.resolve(targetUri);
//    log.info("RESULT: " + uri);
    return uri;
  }

  /**
   * Get URI from a string path.
   */
  public static URI getURIFromPath(String path) {
    URI retUri = null;
    try {
      retUri = new URI(path);
    } catch (URISyntaxException e) {
      throw new IllegalArgumentException("path");
    }
    return retUri;
  }

  public static URI getSourcePartUriFromRelationshipPartUri(
      URI relationshipPartUri) {
    if (relationshipPartUri == null)
      throw new IllegalArgumentException(
          "The relationshipPart Uri was null !");

    if (!isRelationshipPartURI(relationshipPartUri))
      throw new IllegalArgumentException(
          "L'URI ne doit pas �tre celle d'une partie de type relation.");

    if (relationshipPartUri.compareTo(PACKAGE_RELATIONSHIPS_ROOT_URI) == 0)
      return PACKAGE_ROOT_URI;

    String filename = relationshipPartUri.getPath();
    String filenameWithoutExtension = getFilenameWithoutExtension(relationshipPartUri);
    filename = filename
        .substring(0, ((filename.length() - filenameWithoutExtension
            .length()) - RELATIONSHIP_PART_EXTENSION_NAME.length()));
    filename = filename.substring(0, filename.length()
        - RELATIONSHIP_PART_SEGMENT_NAME.length() - 1);
    filename = combine(filename, filenameWithoutExtension);
    return getURIFromPath(filename);
  }

  /**
   * Create an OPC compliant part name by throwing an exception if the URI is
   * not valid.
   *
   * @param partUri
   *            The part name URI to validate.
   * @return A valid part name object, else <code>null</code>.
   * @throws InvalidFormatException
   *             Throws if the specified URI is not OPC compliant.
   */
  public static PartName createPartName(URI partUri)
      throws InvalidFormatException {
    if (partUri == null)
      throw new IllegalArgumentException("partName");

    return new PartName(partUri, true);
  }

  /**
   * Create an OPC compliant part name by throwing an exception if the
   * specified name is not valid.
   *
   * @param partName
   *            The part name to validate.
   * @return The correspondant part name if valid, else <code>null</code>.
   * @throws InvalidFormatException
   *             Throws if the specified part name is not OPC compliant.
   * @see #createPartName(URI)
   */
  public static PartName createPartName(String partName)
      throws InvalidFormatException {
    URI partNameURI;
    try {
      partNameURI = new URI(partName);
    } catch (URISyntaxException e) {
      throw new InvalidFormatException(e.getMessage());
    }
    return createPartName(partNameURI);
  }

  /**
   * Validate a part URI by returning a boolean.
   * ([M1.1],[M1.3],[M1.4],[M1.5],[M1.6])
   *
   * (OPC Specifications 8.1.1 Part names) :
   *
   * Part Name Syntax
   *
   * The part name grammar is defined as follows:
   *
   * <i>part_name = 1*( "/" segment )
   *
   * segment = 1*( pchar )</i>
   *
   *
   * (pchar is defined in RFC 3986)
   *
   * @param partUri
   *            The URI to validate.
   * @return <b>true</b> if the URI is valid to the OPC Specifications, else
   *         <b>false</b>
   *
   * @see #createPartName(URI)
   */
  public static boolean isValidPartName(URI partUri) {
    if (partUri == null)
      throw new IllegalArgumentException("partUri");

    try {
      createPartName(partUri);
      return true;
    } catch (Exception e) {
      return false;
    }
  }

  /**
   * Decode a URI by converting all percent encoded character into a String
   * character.
   *
   * @param uri
   *            The URI to decode.
   * @return The specified URI in a String with converted percent encoded
   *         characters.
   */
  public static String decodeURI(URI uri) {
    StringBuffer retVal = new StringBuffer();
    String uriStr = uri.toASCIIString();
    char c;
    for (int i = 0; i < uriStr.length(); ++i) {
      c = uriStr.charAt(i);
      if (c == '%') {
        // We certainly found an encoded character, check for length
        // now ( '%' HEXDIGIT HEXDIGIT)
        if (((uriStr.length() - i) < 2)) {
          throw new IllegalArgumentException("The uri " + uriStr
              + " contain invalid encoded character !");
        }

        // Decode the encoded character
        char decodedChar = (char) Integer.parseInt(uriStr.substring(
            i + 1, i + 3), 16);
        retVal.append(decodedChar);
        i += 2;
        continue;
      }
      retVal.append(c);
    }
    return retVal.toString();
  }

//  /**
//   * Fully relativize the source part URI against the target part URI.
//   *
//   * @param sourceURI
//   *            The source part URI.
//   * @param targetURI
//   *            The target part URI.
//   * @return A fully relativize part name URI ('word/media/image1.gif',
//   *         '/word/document.xml' => 'media/image1.gif') else
//   *         <code>null</code>.
//   */
//  public static URI OLDrelativizeURI(URI sourceURI, URI targetURI) {
//    StringBuffer retVal = new StringBuffer();
//    String[] segmentsSource = sourceURI.getPath().split("/");
//    String[] segmentsTarget = targetURI.getPath().split("/");
//
//    // If the source URI is empty
//    if (segmentsSource.length == 0) {
//      return null;
//    }
//
//    // If target URI is empty
//    if (segmentsTarget.length == 0) {
//      if (sourceURI.getPath().startsWith(FORWARD_SLASH_STRING)) {
//        try {
//          return new URI(sourceURI.getPath().substring(1));
//        } catch (Exception e) {
//          return null;
//        }
//      } else
//        return sourceURI;
//    }
//
//    // Relativize the source URI against the target URI.
//    for (short i = 0, j = 0; i < segmentsSource.length
//        && j < segmentsTarget.length; ++i, ++j) {
//      if (segmentsSource[i].equalsIgnoreCase(segmentsTarget[j])) {
//        if (i < segmentsSource.length - 1) {
//          continue;
//        } else {
//          // We add the last segment whatever it happens
//          retVal.append("/");
//          retVal.append(segmentsTarget[i]);
//          break;
//        }
//      } else {
//        for (; i < segmentsSource.length; ++i) {
//          retVal.append("/");
//          retVal.append(segmentsSource[i]);
//        }
//        break;
//      }
//    }
//    try {
//      PartName retPartName = new PartName(
//          retVal.toString(), true);
//      return new URI(retPartName.getURI().getPath().substring(1));
//    } catch (Exception e) {
//      return null;
//    }
//  }

 
 
}
TOP

Related Classes of org.docx4j.openpackaging.URIHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.