You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wookie.apache.org by sc...@apache.org on 2010/03/03 19:39:54 UTC

svn commit: r918617 [2/2] - in /incubator/wookie/trunk/parser: ./ java/ java/ant/ java/ant/lib/ java/src-test/ java/src/ java/src/org/ java/src/org/apache/ java/src/org/apache/wookie/ java/src/org/apache/wookie/w3c/ java/src/org/apache/wookie/w3c/excep...

Added: incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/util/UnicodeUtils.java
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/util/UnicodeUtils.java?rev=918617&view=auto
==============================================================================
--- incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/util/UnicodeUtils.java (added)
+++ incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/util/UnicodeUtils.java Wed Mar  3 18:39:52 2010
@@ -0,0 +1,67 @@
+package org.apache.wookie.w3c.util;
+
+import org.apache.commons.lang.CharSetUtils;
+import org.apache.commons.lang.StringUtils;
+
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * A utility class for sanitizing unicode strings in accordance with the rules for 
+ * handling normalized text content and attributes set out in the W3C Widgets
+ * specification
+ */
+public class UnicodeUtils {
+	
+	/**
+	 * Normalizes all whitespace and space characters in the given string to 
+	 * U+0020, then collapses multiple adjacent spaces to a single space, and
+	 * removes any leading and trailing spaces. If the input string is null,
+	 * the method returns an empty string ("")
+	 * @param in the string to normalize
+	 * @return the normalized string
+	 */
+	public static String normalizeWhitespace(String in){
+		return normalize(in, true);
+	}
+	
+	/**
+	 * Normalizes all space characters in the given string to 
+	 * U+0020, then collapses multiple adjacent spaces to a single space, and
+	 * removes any leading and trailing spaces. If the input string is null,
+	 * the method returns an empty string ("")
+	 * @param in the string to normalize
+	 * @return the normalized string
+	 */
+	public static String normalizeSpaces(String in){
+		return normalize(in, false);
+	}
+	
+	private static String normalize(String in, boolean includeWhitespace){
+		if (in == null) return "";
+		String out = "";
+		for (int x=0;x<in.length();x++){
+			String s = in.substring(x, x+1);
+			char ch = s.charAt(0);
+			if (Character.isSpaceChar(ch) || (Character.isWhitespace(ch) && includeWhitespace)){
+				s = " ";
+			}
+			out = out + s;
+		}
+		out = CharSetUtils.squeeze(out, " ");
+		out = StringUtils.strip(out);
+		return out;
+	}
+
+}

Added: incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/util/WidgetPackageUtils.java
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/util/WidgetPackageUtils.java?rev=918617&view=auto
==============================================================================
--- incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/util/WidgetPackageUtils.java (added)
+++ incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/util/WidgetPackageUtils.java Wed Mar  3 18:39:52 2010
@@ -0,0 +1,363 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wookie.w3c.util;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipFile;
+import org.apache.commons.fileupload.DiskFileUpload;
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileUploadBase;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.Logger;
+import org.apache.wookie.w3c.util.LocalizationUtils;
+import org.apache.wookie.w3c.IContentEntity;
+import org.apache.wookie.w3c.W3CWidget;
+import org.apache.wookie.w3c.IStartPageProcessor;
+import org.apache.wookie.w3c.IW3CXMLConfiguration;
+import org.apache.wookie.w3c.exceptions.BadManifestException;
+import org.apache.wookie.w3c.exceptions.BadWidgetZipFileException;
+import org.apache.wookie.w3c.exceptions.InvalidStartFileException;
+import org.apache.wookie.w3c.impl.WidgetManifestModel;
+
+/**
+ * Utilities for working with Widget packages, i.e. Zip Files with an XML manifest
+ * @author scott
+ *
+ */
+public class WidgetPackageUtils {
+	static Logger _logger = Logger.getLogger(WidgetPackageUtils.class.getName());
+	
+	/**
+	 * Implements the rule for finding a file within a widget; it returns the first localized version 
+	 * first before returning a root version. An exception is thrown if the path points to a folder, and
+	 * null is returned if no file is found
+	 * @param path
+	 * @param locales the supported locales, in list of preference
+	 * @param zip
+	 * @return
+	 * @throws Exception
+	 */
+	public static String locateFilePath(String path, String[] locales, ZipFile zip) throws Exception{
+		String[] paths = locateFilePaths(path, locales, zip);
+		if (paths != null && paths.length != 0) return paths[0];
+		return null;
+	}
+	
+	/**
+	 * Returns the set of valid file paths for a given resource. All valid paths are returned, starting
+	 * with localized versions for supported locales before the root version (if present).
+	 * @param path
+	 * @param locales
+	 * @param zip
+	 * @return
+	 * @throws Exception
+	 */
+	public static String[] locateFilePaths(String path, String[] locales, ZipFile zip) throws Exception{
+		ArrayList<String> paths = new ArrayList<String>();
+		if (path.startsWith("/")) path = path.substring(1, path.length());
+		String[] pathComponents = path.split("/");
+		if ("locales".equalsIgnoreCase(pathComponents[0])){
+			if (pathComponents.length < 2) return null;
+			if (!LocalizationUtils.isValidLanguageTag(pathComponents[1])) return null;
+		}
+		// Look in localized folders first
+		for (String locale:locales){
+			String localePath = "locales/"+locale.trim()+"/"+path;
+			if (zip.getEntry(localePath) != null){
+				if (zip.getEntry(localePath).isDirectory()) throw new Exception();
+				paths.add(localePath);
+			}
+		}
+		// Look in root folder
+		if (zip.getEntry(path) != null && !zip.getEntry(path).isDirectory()) paths.add(path);
+		return (String[]) paths.toArray(new String[paths.size()]);
+	}
+	
+	/**
+	 * Return the language tag for a given path
+	 * @param path
+	 * @return
+	 */
+	public static String languageTagForPath(String path){
+		if (path == null) return null;
+		String locale = null;
+		String[] pathComponents = path.split("/");
+		if ("locales".equalsIgnoreCase(pathComponents[0])){
+			if (pathComponents.length < 2) return null;
+			return pathComponents[1];
+		}
+		return locale;
+	}
+	
+	/**
+	 * Return the set of valid default files for each locale in the zip
+	 * @param zip
+	 * @param locales
+	 * @param defaults
+	 * @return
+	 */
+	public static String[] getDefaults(ZipFile zip, String[] locales, String[] defaults){
+		ArrayList<String> content = new ArrayList<String>();
+		for (String start: defaults){
+			try {
+				String[] paths = locateFilePaths(start, locales, zip);
+				if (paths != null){
+					for (String path:paths) content.add(path);
+				}
+			} catch (Exception e) {
+				// ignore and move onto next
+			}
+		}
+		return (String[]) content.toArray(new String[content.size()]);	
+	}
+	
+	public static File createUnpackedWidgetFolder(String widgetFolder, String folder) throws IOException{
+		folder = convertIdToFolderName(folder);
+		String serverPath = widgetFolder + File.separator + folder;
+		File file = new File(convertPathToPlatform(serverPath));
+		return file;
+	}
+
+	public static String getURLForWidget(String widgetFolder, String folder, String file){
+		folder = convertIdToFolderName(folder);
+		String path = convertPathToRelativeUri("/wookie" + widgetFolder + File.separator + folder + File.separator + file); //$NON-NLS-1$ //$NON-NLS-2$
+		return path;
+	}
+	
+	public static String convertIdToFolderName(String folder){
+		if(folder.startsWith("http://")){ //$NON-NLS-1$
+			folder = folder.substring(7, folder.length());
+		}
+		folder.replaceAll(" ", ""); //$NON-NLS-1$ //$NON-NLS-2$
+		return folder;
+	}
+	
+	public static File dealWithDroppedFile(String uploadPath, File file) throws IOException{	
+		String serverPath = convertPathToPlatform(uploadPath);
+		File uFile = new File(serverPath + File.separator + file.getName());
+		FileUtils.copyFile(file, uFile);
+		file.delete();
+		return uFile;
+	}
+
+	public static File dealWithUploadFile(String uploadPath, HttpServletRequest request) throws Exception {
+		File uFile = null;
+		String serverPath = convertPathToPlatform(uploadPath);
+		_logger.debug(serverPath);
+		String archiveFileName = null;
+		if (FileUploadBase.isMultipartContent(request)) {
+			_logger.debug("uploading file..."); //$NON-NLS-1$
+			DiskFileUpload fu = new DiskFileUpload();
+			// maximum size before a FileUploadException will be thrown
+			fu.setSizeMax(1024 * 1024 * 1024);
+			// maximum size that will be stored in memory
+			fu.setSizeThreshold(1024 * 1024);
+			// the location for saving data that is larger than
+			// getSizeThreshold()
+			fu.setRepositoryPath(uploadPath);
+
+			List<?> fileItems = fu.parseRequest(request);
+			if (!fileItems.isEmpty()) {
+				Iterator<?> i = fileItems.iterator();
+				FileItem fi = (FileItem) i.next();
+				File file = new File(convertPathToPlatform(fi.getName()));
+				archiveFileName = file.getName();
+
+				uFile = new File(serverPath + File.separator + archiveFileName);
+
+				fi.write(uFile);
+				_logger.debug("Upload completed successfully" +  "[" //$NON-NLS-1$ //$NON-NLS-2$
+						+ archiveFileName + "]-" //$NON-NLS-1$
+						+ (fi.isInMemory() ? "M" : "D")); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		}
+		return uFile;
+	}
+
+
+	public static String convertPathToRelativeUri(String path){
+		return path.replace('\\', '/');
+	}
+
+	public static String convertPathToPlatform(String path) {
+		String result = path.replace('\\', '/')
+		.replace('/', File.separatorChar);
+		if (result.endsWith(File.separator)) {
+			result = result.substring(0, result.length() - 1);
+		}
+		return result;
+	}
+
+	public static boolean removeWidgetResources(String WIDGETFOLDER, String widgetGuid){
+		String folder = convertIdToFolderName(widgetGuid);
+		String serverPath = WIDGETFOLDER + File.separator + folder;
+		File pFolder = new File(convertPathToPlatform(serverPath));
+		try {
+			_logger.debug("Deleting folder:"+pFolder.getCanonicalFile().toString()); //$NON-NLS-1$
+			if (pFolder.getParent() != null) // never call on a root folder
+				FileUtils.deleteDirectory(pFolder);
+		}
+		catch (Exception ex) {
+			_logger.error(ex);
+		}
+		return true;
+	}
+	
+	public static W3CWidget processWidgetPackage(File zipFile, String localWidgetPath, String WIDGETFOLDER, String[] locales, IStartPageProcessor processor, String[] features) throws BadWidgetZipFileException, BadManifestException{
+		ZipFile zip;
+		try {
+			zip = new ZipFile(zipFile);
+		} catch (IOException e) {
+			throw new BadWidgetZipFileException();
+		}
+		if (WidgetPackageUtils.hasManifest(zip)){
+			try {
+				// build the model
+				W3CWidget widgetModel = new WidgetManifestModel(WidgetPackageUtils.extractManifest(zip), locales, features, zip);															
+
+				// get the widget identifier
+				String manifestIdentifier = widgetModel.getIdentifier();						
+				// create the folder structure to unzip the zip into
+				File newWidgetFolder = WidgetPackageUtils.createUnpackedWidgetFolder(WIDGETFOLDER, manifestIdentifier);
+				// now unzip it into that folder
+				WidgetPackageUtils.unpackZip(zip, newWidgetFolder);	
+				
+				// Iterate over all start files and update paths
+				for (IContentEntity content: widgetModel.getContentList()){
+					// now update the js links in the start page
+					File startFile = new File(newWidgetFolder.getCanonicalPath() + File.separator + content.getSrc());
+					String relativestartUrl = (WidgetPackageUtils.getURLForWidget(localWidgetPath, manifestIdentifier, content.getSrc())); 					
+					content.setSrc(relativestartUrl);
+					if(startFile.exists()){		
+						processor.processStartFile(startFile, widgetModel);
+					}	
+				}
+				if (widgetModel.getContentList().isEmpty()){
+					throw new InvalidStartFileException();
+				}
+				
+				// get the path to the root of the unzipped folder
+				String localPath = WidgetPackageUtils.getURLForWidget(localWidgetPath, manifestIdentifier, "");
+				// now pass this to the model which will prepend the path to local resources (not web icons)
+				widgetModel.updateIconPaths(localPath);				
+				
+				// check to see if this widget already exists in the DB - using the ID (guid) key from the manifest
+				return widgetModel;
+			} catch (InvalidStartFileException e) {
+				throw e;
+			} catch (BadManifestException e) {
+				throw e;
+			} catch (Exception e){
+				throw new BadManifestException();
+			}
+		}
+		else{
+			// no manifest file found in zip archive
+			throw new BadWidgetZipFileException(); //$NON-NLS-1$ 
+		}
+	}
+	
+	/**
+	 * Checks for the existence of the Manifest.
+	 * TODO not sure if this properly handles case-sensitive entries?
+	 * @param zipfile
+	 * @return true if the zip file has a manifest
+	 */
+	public static boolean hasManifest(ZipFile zipfile){
+		return zipfile.getEntry(IW3CXMLConfiguration.MANIFEST_FILE)!=null;
+	}
+
+	/**
+	 * Retrieves the Manifest entry as a String
+	 * @param zipFile the zip file from which to extract the manifest
+	 * @return a String representing the manifest contents
+	 * @throws IOException
+	 */
+	public static String extractManifest(ZipFile zipFile) throws IOException{
+		ZipArchiveEntry entry = zipFile.getEntry(IW3CXMLConfiguration.MANIFEST_FILE);
+		return IOUtils.toString(zipFile.getInputStream(entry));
+	}
+
+	/**
+	 * uses apache commons compress to unpack all the zip entries into a target folder
+	 * partly adapted from the examples on the apache commons compress site, and an
+	 * example of generic Zip unpacking. Note this iterates over the ZipArchiveEntry enumeration rather
+	 * than use the more typical ZipInputStream parsing model, as according to the doco it will
+	 * more reliably read the entries correctly. More info here: http://commons.apache.org/compress/zip.html
+	 * @param zipfile the Zip File to unpack
+	 * @param targetFolder the folder into which to unpack the Zip file
+	 * @throws IOException
+	 */
+	@SuppressWarnings("unchecked")
+	public static void unpackZip(ZipFile zipfile, File targetFolder) throws IOException {
+		targetFolder.mkdirs();
+		BufferedOutputStream out = null;
+		InputStream in = null;
+		ZipArchiveEntry zipEntry;
+
+		Enumeration entries = zipfile.getEntries();
+		try {
+			while (entries.hasMoreElements()){
+				zipEntry = (ZipArchiveEntry)entries.nextElement();
+				// Don't add directories - use mkdirs instead
+				if(!zipEntry.isDirectory()) {
+					File outFile = new File(targetFolder, zipEntry.getName());
+
+					// Ensure that the parent Folder exists
+					if(!outFile.getParentFile().exists()) {
+						outFile.getParentFile().mkdirs();
+					}
+					// Read the entry
+					in = new BufferedInputStream(zipfile.getInputStream(zipEntry));
+					out = new BufferedOutputStream(new FileOutputStream(outFile));
+					IOUtils.copy(in, out);
+					// Restore time stamp
+					outFile.setLastModified(zipEntry.getTime());
+					
+					// Close File
+					out.close();
+					// Close Stream
+					in.close();
+				}
+			}
+
+		}
+		// We'll catch this exception to close the file otherwise it remains locked
+		catch(IOException ex) {
+			if (in != null){
+				in.close();
+			}
+			if(out != null) {
+				out.flush();
+				out.close();
+			}
+			// And throw it again
+			throw ex;
+		}
+	}
+}

Copied: incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/util/XmlUtils.java (from r888585, incubator/wookie/trunk/src/org/apache/wookie/util/XmlUtils.java)
URL: http://svn.apache.org/viewvc/incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/util/XmlUtils.java?p2=incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/util/XmlUtils.java&p1=incubator/wookie/trunk/src/org/apache/wookie/util/XmlUtils.java&r1=888585&r2=918617&rev=918617&view=diff
==============================================================================
--- incubator/wookie/trunk/src/org/apache/wookie/util/XmlUtils.java (original)
+++ incubator/wookie/trunk/parser/java/src/org/apache/wookie/w3c/util/XmlUtils.java Wed Mar  3 18:39:52 2010
@@ -11,7 +11,7 @@
  *  See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.wookie.util;
+package org.apache.wookie.w3c.util;
 
 import org.jdom.Element;
 import org.jdom.Text;