001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/archive/tags/sakai_2-4-1/import-impl/src/java/org/sakaiproject/importer/impl/ZipFileParser.java $
003: * $Id: ZipFileParser.java 17726 2006-11-01 15:39:28Z lance@indiana.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.importer.impl;
021:
022: import java.io.ByteArrayInputStream;
023: import java.io.File;
024: import java.io.FileInputStream;
025: import java.io.FileOutputStream;
026: import java.io.IOException;
027: import java.io.InputStream;
028: import java.util.ArrayList;
029: import java.util.Collection;
030: import java.util.List;
031: import java.util.Set;
032: import java.util.TreeSet;
033: import java.util.zip.ZipEntry;
034: import java.util.zip.ZipInputStream;
035: import javax.activation.MimetypesFileTypeMap;
036: import javax.xml.parsers.DocumentBuilder;
037: import javax.xml.parsers.DocumentBuilderFactory;
038: import javax.xml.parsers.FactoryConfigurationError;
039: import javax.xml.parsers.ParserConfigurationException;
040:
041: import org.sakaiproject.importer.api.ImportDataSource;
042: import org.sakaiproject.importer.api.ImportFileParser;
043: import org.w3c.dom.Document;
044: import org.xml.sax.SAXException;
045:
046: public abstract class ZipFileParser implements ImportFileParser {
047: protected MimetypesFileTypeMap mimeTypes = new MimetypesFileTypeMap();
048: protected String pathToData;
049: protected String localArchiveLocation;
050:
051: public boolean isValidArchive(byte[] fileData) {
052: ZipInputStream zipStream = new ZipInputStream(
053: new ByteArrayInputStream(fileData));
054: ZipEntry entry;
055: try {
056: entry = (ZipEntry) zipStream.getNextEntry();
057: } catch (IOException e) {
058: // IOException definitely indicates not a valid archive
059: return false;
060: }
061: return (entry != null);
062: }
063:
064: public ImportDataSource parse(byte[] fileData,
065: String unArchiveLocation) {
066: this .localArchiveLocation = unzipArchive(fileData,
067: unArchiveLocation);
068: this .pathToData = unArchiveLocation + "/"
069: + localArchiveLocation;
070: awakeFromUnzip(pathToData);
071: List categories = new ArrayList();
072: Collection items = new ArrayList();
073: categories.addAll(getCategoriesFromArchive(pathToData));
074: items.addAll(getImportableItemsFromArchive(pathToData));
075:
076: ImportDataSource dataSource = new BasicImportDataSource();
077: dataSource.setItemCategories(categories);
078: dataSource.setItems(items);
079: return dataSource;
080: }
081:
082: protected abstract void awakeFromUnzip(String unArchiveLocation);
083:
084: protected abstract Collection getImportableItemsFromArchive(
085: String pathToData);
086:
087: protected abstract Collection getCategoriesFromArchive(
088: String pathToData);
089:
090: protected String unzipArchive(byte[] fileData,
091: String unArchiveLocation) {
092: String localArchiveLocation = Long
093: .toString(new java.util.Date().getTime());
094: String pathToData = unArchiveLocation + "/"
095: + localArchiveLocation;
096: File dir = new File(pathToData); //directory where file would be saved
097: if (!dir.exists()) {
098: dir.mkdirs();
099: }
100:
101: try {
102: Set dirsMade = new TreeSet();
103: ZipInputStream zipStream = new ZipInputStream(
104: new ByteArrayInputStream(fileData));
105: ZipEntry entry = (ZipEntry) zipStream.getNextEntry();
106: while (entry != null) {
107: String zipName = entry.getName();
108:
109: //for attachment type files
110: // Get the directory part.
111: int ix = zipName.lastIndexOf('/');
112: if (ix > 0) {
113: String dirName = zipName.substring(0, ix);
114: if (!dirsMade.contains(dirName)) {
115: File d = new File(dir.getPath() + "/" + dirName);
116: // If it already exists as a dir, don't do anything
117: if (!(d.exists() && d.isDirectory())) {
118: // Try to create the directory, warn if it fails
119: if (!d.mkdirs()) {
120: //Log.warn("Warning: unable to mkdir " + dir.getPath() + "/" + dirName);
121: }
122: dirsMade.add(dirName);
123: }
124: }
125: }
126: File zipEntryFile = new File(dir.getPath() + "/"
127: + entry.getName());
128: if (!zipEntryFile.isDirectory()) {
129: FileOutputStream ofile = new FileOutputStream(
130: zipEntryFile);
131: byte[] buffer = new byte[1024 * 10];
132: int bytesRead;
133: while ((bytesRead = zipStream.read(buffer)) != -1) {
134: ofile.write(buffer, 0, bytesRead);
135: }
136:
137: ofile.close();
138: }
139: zipStream.closeEntry();
140: entry = zipStream.getNextEntry();
141: }
142: } catch (Exception e5) {
143: // todo handle errors
144: e5.printStackTrace();
145: }
146: return localArchiveLocation;
147: }
148:
149: protected boolean fileExistsInArchive(String pathAndFilename,
150: byte[] archive) {
151: ZipInputStream zipStream = new ZipInputStream(
152: new ByteArrayInputStream(archive));
153: ZipEntry entry;
154: String entryName;
155: if (pathAndFilename.charAt(0) == '/') {
156: pathAndFilename = pathAndFilename.substring(1);
157: }
158: try {
159: entry = (ZipEntry) zipStream.getNextEntry();
160: while (entry != null) {
161: entryName = entry.getName();
162: if (entryName.equals(pathAndFilename))
163: return true;
164: entry = (ZipEntry) zipStream.getNextEntry();
165: }
166: return false;
167: } catch (IOException e) {
168: return false;
169: }
170: }
171:
172: protected Document extractFileAsDOM(String pathAndFilename,
173: byte[] archive) {
174: ZipInputStream zipStream = new ZipInputStream(
175: new ByteArrayInputStream(archive));
176: ZipEntry entry;
177: String entryName;
178: if (pathAndFilename.charAt(0) == '/') {
179: pathAndFilename = pathAndFilename.substring(1);
180: }
181: DocumentBuilder docBuilder;
182: try {
183: docBuilder = DocumentBuilderFactory.newInstance()
184: .newDocumentBuilder();
185: entry = (ZipEntry) zipStream.getNextEntry();
186: while (entry != null) {
187: entryName = entry.getName();
188: if (entryName.equals(pathAndFilename)) {
189: return (Document) docBuilder.parse(zipStream);
190: }
191: entry = (ZipEntry) zipStream.getNextEntry();
192: }
193: return null;
194: } catch (IOException e) {
195: e.printStackTrace();
196: return null;
197: } catch (ParserConfigurationException e) {
198: e.printStackTrace();
199: return null;
200: } catch (FactoryConfigurationError e) {
201: e.printStackTrace();
202: return null;
203: } catch (SAXException e) {
204: e.printStackTrace();
205: return null;
206: }
207: }
208:
209: protected byte[] getBytesFromFile(File file) throws IOException {
210: InputStream is = new FileInputStream(file);
211:
212: // Get the size of the file
213: long length = file.length();
214:
215: // You cannot create an array using a long type.
216: // It needs to be an int type.
217: // Before converting to an int type, check
218: // to ensure that file is not larger than Integer.MAX_VALUE.
219: if (length > Integer.MAX_VALUE) {
220: // File is too large
221: }
222:
223: // Create the byte array to hold the data
224: byte[] bytes = new byte[(int) length];
225:
226: // Read in the bytes
227: int offset = 0;
228: int numRead = 0;
229: while (offset < bytes.length
230: && (numRead = is.read(bytes, offset, bytes.length
231: - offset)) >= 0) {
232: offset += numRead;
233: }
234:
235: // Ensure all the bytes have been read in
236: if (offset < bytes.length) {
237: throw new IOException("Could not completely read file "
238: + file.getName());
239: }
240:
241: // Close the input stream and return bytes
242: is.close();
243: return bytes;
244: }
245:
246: }
|