001: /*
002: * File : $Source: /usr/local/cvs/opencms/src/org/opencms/db/CmsImportFolder.java,v $
003: * Date : $Date: 2008-03-17 14:51:49 $
004: * Version: $Revision: 1.40 $
005: *
006: * This library is part of OpenCms -
007: * the Open Source Content Management System
008: *
009: * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
010: *
011: * This library is free software; you can redistribute it and/or
012: * modify it under the terms of the GNU Lesser General Public
013: * License as published by the Free Software Foundation; either
014: * version 2.1 of the License, or (at your option) any later version.
015: *
016: * This library is distributed in the hope that it will be useful,
017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: * Lesser General Public License for more details.
020: *
021: * For further information about Alkacon Software GmbH, please see the
022: * company website: http://www.alkacon.com
023: *
024: * For further information about OpenCms, please see the
025: * project website: http://www.opencms.org
026: *
027: * You should have received a copy of the GNU Lesser General Public
028: * License along with this library; if not, write to the Free Software
029: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
030: */
031:
032: package org.opencms.db;
033:
034: import org.opencms.file.CmsFile;
035: import org.opencms.file.CmsObject;
036: import org.opencms.file.CmsProperty;
037: import org.opencms.file.CmsPropertyDefinition;
038: import org.opencms.file.CmsResource;
039: import org.opencms.file.CmsResourceFilter;
040: import org.opencms.file.CmsVfsException;
041: import org.opencms.file.types.CmsResourceTypeFolder;
042: import org.opencms.file.types.CmsResourceTypePlain;
043: import org.opencms.main.CmsEvent;
044: import org.opencms.main.CmsException;
045: import org.opencms.main.I_CmsEventListener;
046: import org.opencms.main.OpenCms;
047: import org.opencms.security.CmsSecurityException;
048: import org.opencms.util.CmsFileUtil;
049:
050: import java.io.ByteArrayInputStream;
051: import java.io.File;
052: import java.io.FileInputStream;
053: import java.io.IOException;
054: import java.util.ArrayList;
055: import java.util.Collections;
056: import java.util.List;
057: import java.util.StringTokenizer;
058: import java.util.zip.ZipEntry;
059: import java.util.zip.ZipInputStream;
060:
061: /**
062: * Allows to import resources from the filesystem or a ZIP file into the OpenCms VFS.<p>
063: *
064: * @author Alexander Kandzior
065: *
066: * @version $Revision: 1.40 $
067: *
068: * @since 6.0.0
069: */
070: public class CmsImportFolder {
071:
072: /** The OpenCms context object that provides the permissions. */
073: private CmsObject m_cms;
074:
075: /** The name of the import folder to load resources from. */
076: private String m_importFolderName;
077:
078: /** The import path in the OpenCms VFS. */
079: private String m_importPath;
080:
081: /** The resource (folder or ZIP file) to import from in the real file system. */
082: private File m_importResource;
083:
084: /** Will be true if the import resource is a valid ZIP file. */
085: private boolean m_validZipFile;
086:
087: /** The import resource ZIP stream to load resources from. */
088: private ZipInputStream m_zipStreamIn;
089:
090: /**
091: * Constructor for a new CmsImportFolder that will read from a ZIP file.<p>
092: *
093: * @param content the zip file to import
094: * @param importPath the path to the OpenCms VFS to import to
095: * @param cms a OpenCms context to provide the permissions
096: * @param noSubFolder if false no sub folder will be created
097: * @throws CmsException if something goes wrong
098: */
099: public CmsImportFolder(byte[] content, String importPath,
100: CmsObject cms, boolean noSubFolder) throws CmsException {
101:
102: m_importPath = importPath;
103: m_cms = cms;
104: try {
105: // open the import resource
106: m_zipStreamIn = new ZipInputStream(
107: new ByteArrayInputStream(content));
108: m_cms.readFolder(importPath,
109: CmsResourceFilter.IGNORE_EXPIRATION);
110: // import the resources
111: importZipResource(m_zipStreamIn, m_importPath, noSubFolder);
112: } catch (Exception e) {
113: throw new CmsVfsException(Messages.get().container(
114: Messages.ERR_IMPORT_FOLDER_1, importPath), e);
115: }
116: }
117:
118: /**
119: * Constructor for a new CmsImportFolder that will read from the real file system.<p>
120: *
121: * @param importFolderName the folder to import
122: * @param importPath the path to the OpenCms VFS to import to
123: * @param cms a OpenCms context to provide the permissions
124: * @throws CmsException if something goes wrong
125: */
126: public CmsImportFolder(String importFolderName, String importPath,
127: CmsObject cms) throws CmsException {
128:
129: try {
130: m_importFolderName = importFolderName;
131: m_importPath = importPath;
132: m_cms = cms;
133: // open the import resource
134: getImportResource();
135: // first lock the destination path
136: m_cms.lockResource(m_importPath);
137: // import the resources
138: if (m_zipStreamIn == null) {
139: importResources(m_importResource, m_importPath);
140: } else {
141: importZipResource(m_zipStreamIn, m_importPath, false);
142: }
143: // all is done, unlock the resources
144: m_cms.unlockResource(m_importPath);
145: } catch (Exception e) {
146: throw new CmsVfsException(Messages.get().container(
147: Messages.ERR_IMPORT_FOLDER_2, importFolderName,
148: importPath), e);
149: }
150: }
151:
152: /**
153: * Returns true if a valid ZIP file was imported.<p>
154: *
155: * @return true if a valid ZIP file was imported
156: */
157: public boolean isValidZipFile() {
158:
159: return m_validZipFile;
160: }
161:
162: /**
163: * Stores the import resource in an Object member variable.<p>
164: * @throws CmsVfsException if the file to import is no valid zipfile
165: */
166: private void getImportResource() throws CmsVfsException {
167:
168: // get the import resource
169: m_importResource = new File(m_importFolderName);
170: // check if this is a folder or a ZIP file
171: if (m_importResource.isFile()) {
172: try {
173: m_zipStreamIn = new ZipInputStream(new FileInputStream(
174: m_importResource));
175: } catch (IOException e) {
176: // if file but no ZIP file throw an exception
177: throw new CmsVfsException(Messages.get().container(
178: Messages.ERR_NO_ZIPFILE_1,
179: m_importResource.getName()), e);
180: }
181: }
182: }
183:
184: /**
185: * Imports the resources from the folder in the real file system to the OpenCms VFS.<p>
186: *
187: * @param folder the folder to import from
188: * @param importPath the OpenCms VFS import path to import to
189: * @throws Exception if something goes wrong during file IO
190: */
191: private void importResources(File folder, String importPath)
192: throws Exception {
193:
194: String[] diskFiles = folder.list();
195: File currentFile;
196:
197: for (int i = 0; i < diskFiles.length; i++) {
198: currentFile = new File(folder, diskFiles[i]);
199:
200: if (currentFile.isDirectory()) {
201: // create directory in cms
202: m_cms.createResource(
203: importPath + currentFile.getName(),
204: CmsResourceTypeFolder.RESOURCE_TYPE_ID);
205: importResources(currentFile, importPath
206: + currentFile.getName() + "/");
207: } else {
208: // import file into cms
209: int type = OpenCms.getResourceManager()
210: .getDefaultTypeForName(currentFile.getName())
211: .getTypeId();
212: byte[] content = CmsFileUtil.readFile(currentFile);
213: // create the file
214: try {
215: m_cms.createResource(importPath
216: + currentFile.getName(), type, content,
217: null);
218: } catch (CmsSecurityException e) {
219: // in case of not enough permissions, try to create a plain text file
220: m_cms.createResource(importPath
221: + currentFile.getName(),
222: CmsResourceTypePlain.getStaticTypeId(),
223: content, null);
224: }
225: content = null;
226: }
227: }
228: }
229:
230: /**
231: * Imports the resources from a ZIP file in the real file system to the OpenCms VFS.<p>
232: *
233: * @param zipStreamIn the input Stream
234: * @param importPath the path in the vfs
235: * @param noSubFolder create subFolders or not
236: * @throws Exception if something goes wrong during file IO
237: */
238: private void importZipResource(ZipInputStream zipStreamIn,
239: String importPath, boolean noSubFolder) throws Exception {
240:
241: int todo = 0;
242: // TODO: this method looks very crude, it should be re-written sometime...
243:
244: boolean isFolder = false;
245: int j, r, stop, size;
246: int entries = 0;
247: byte[] buffer = null;
248: boolean resourceExists;
249:
250: while (true) {
251: // handle the single entries ...
252: j = 0;
253: stop = 0;
254: // open the entry ...
255: ZipEntry entry = zipStreamIn.getNextEntry();
256: if (entry == null) {
257: break;
258: }
259: entries++; // count number of entries in zip
260: String actImportPath = importPath;
261: String title = CmsResource.getName(entry.getName());
262: String filename = m_cms.getRequestContext()
263: .getFileTranslator().translateResource(
264: entry.getName());
265: // separate path in directories an file name ...
266: StringTokenizer st = new StringTokenizer(filename, "/\\");
267: int count = st.countTokens();
268: String[] path = new String[count];
269:
270: if (filename.endsWith("\\") || filename.endsWith("/")) {
271: isFolder = true; // last entry is a folder
272: } else {
273: isFolder = false; // last entry is a file
274: }
275: while (st.hasMoreTokens()) {
276: // store the files and folder names in array ...
277: path[j] = st.nextToken();
278: j++;
279: }
280: stop = isFolder ? path.length : (path.length - 1);
281:
282: if (noSubFolder) {
283: stop = 0;
284: }
285: // now write the folders ...
286: for (r = 0; r < stop; r++) {
287: try {
288: m_cms.createResource(actImportPath + path[r],
289: CmsResourceTypeFolder.RESOURCE_TYPE_ID);
290: } catch (CmsException e) {
291: // of course some folders did already exist!
292: }
293: actImportPath += path[r];
294: actImportPath += "/";
295: }
296: if (!isFolder) {
297: // import file into cms
298: int type = OpenCms.getResourceManager()
299: .getDefaultTypeForName(path[path.length - 1])
300: .getTypeId();
301: size = new Long(entry.getSize()).intValue();
302: if (size == -1) {
303: buffer = CmsFileUtil.readFully(zipStreamIn, false);
304: } else {
305: buffer = CmsFileUtil.readFully(zipStreamIn, size,
306: false);
307: }
308: filename = actImportPath + path[path.length - 1];
309:
310: try {
311: m_cms.lockResource(filename);
312:
313: m_cms.readResource(filename);
314: resourceExists = true;
315: } catch (CmsException e) {
316: resourceExists = false;
317: }
318:
319: if (resourceExists) {
320: CmsResource res = m_cms.readResource(filename,
321: CmsResourceFilter.ALL);
322: CmsFile file = m_cms.readFile(res);
323: byte[] contents = file.getContents();
324: try {
325: m_cms.replaceResource(filename,
326: res.getTypeId(), buffer,
327: Collections.EMPTY_LIST);
328: } catch (CmsSecurityException e) {
329: // in case of not enough permissions, try to create a plain text file
330: m_cms.replaceResource(filename,
331: CmsResourceTypePlain.getStaticTypeId(),
332: buffer, Collections.EMPTY_LIST);
333: } catch (CmsDbSqlException sqlExc) {
334: // SQL error, probably the file is too large for the database settings, restore content
335: file.setContents(contents);
336: m_cms.writeFile(file);
337: throw sqlExc;
338: }
339:
340: OpenCms
341: .fireCmsEvent(new CmsEvent(
342: I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED,
343: Collections.singletonMap(
344: "resource", res)));
345: } else {
346: String newResName = actImportPath
347: + path[path.length - 1];
348: if (title.lastIndexOf('.') != -1) {
349: title = title.substring(0, title
350: .lastIndexOf('.'));
351: }
352: List properties = new ArrayList(1);
353: CmsProperty titleProp = new CmsProperty();
354: titleProp
355: .setName(CmsPropertyDefinition.PROPERTY_TITLE);
356: if (OpenCms.getWorkplaceManager()
357: .isDefaultPropertiesOnStructure()) {
358: titleProp.setStructureValue(title);
359: } else {
360: titleProp.setResourceValue(title);
361: }
362: properties.add(titleProp);
363: try {
364: m_cms.createResource(newResName, type, buffer,
365: properties);
366: } catch (CmsSecurityException e) {
367: // in case of not enough permissions, try to create a plain text file
368: m_cms.createResource(newResName,
369: CmsResourceTypePlain.getStaticTypeId(),
370: buffer, properties);
371: } catch (CmsDbSqlException sqlExc) {
372: // SQL error, probably the file is too large for the database settings, delete file
373: m_cms.lockResource(newResName);
374: m_cms.deleteResource(newResName,
375: CmsResource.DELETE_PRESERVE_SIBLINGS);
376: throw sqlExc;
377: }
378: }
379: }
380:
381: // close the entry ...
382: zipStreamIn.closeEntry();
383: }
384: zipStreamIn.close();
385: if (entries > 0) {
386: // at least one entry, got a valid zip file ...
387: m_validZipFile = true;
388: }
389: }
390: }
|