Source Code Cross Referenced for ShadingPathResolver.java in  » Development » Java-Plugin-Framework » org » java » plugin » standard » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Development » Java Plugin Framework » org.java.plugin.standard 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*****************************************************************************
002:         * Java Plug-in Framework (JPF)
003:         * Copyright (C) 2004-2007 Dmitry Olshansky
004:         * 
005:         * This library is free software; you can redistribute it and/or
006:         * modify it under the terms of the GNU Lesser General Public
007:         * License as published by the Free Software Foundation; either
008:         * version 2.1 of the License, or (at your option) any later version.
009:         * 
010:         * This library is distributed in the hope that it will be useful,
011:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
012:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013:         * Lesser General Public License for more details.
014:         * 
015:         * You should have received a copy of the GNU Lesser General Public
016:         * License along with this library; if not, write to the Free Software
017:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018:         *****************************************************************************/package org.java.plugin.standard;
019:
020:        import java.io.BufferedInputStream;
021:        import java.io.BufferedOutputStream;
022:        import java.io.File;
023:        import java.io.FileFilter;
024:        import java.io.FileInputStream;
025:        import java.io.FileOutputStream;
026:        import java.io.IOException;
027:        import java.io.InputStream;
028:        import java.io.OutputStream;
029:        import java.net.JarURLConnection;
030:        import java.net.MalformedURLException;
031:        import java.net.URL;
032:        import java.net.URLConnection;
033:        import java.text.DateFormat;
034:        import java.text.ParseException;
035:        import java.text.SimpleDateFormat;
036:        import java.util.Calendar;
037:        import java.util.Collection;
038:        import java.util.Date;
039:        import java.util.Enumeration;
040:        import java.util.HashMap;
041:        import java.util.HashSet;
042:        import java.util.LinkedList;
043:        import java.util.Locale;
044:        import java.util.Map;
045:        import java.util.Properties;
046:        import java.util.Set;
047:        import java.util.StringTokenizer;
048:        import java.util.regex.Pattern;
049:        import java.util.zip.ZipEntry;
050:        import java.util.zip.ZipFile;
051:        import java.util.zip.ZipInputStream;
052:
053:        import org.apache.commons.logging.Log;
054:        import org.apache.commons.logging.LogFactory;
055:        import org.java.plugin.registry.Identity;
056:        import org.java.plugin.registry.Library;
057:        import org.java.plugin.registry.PluginAttribute;
058:        import org.java.plugin.registry.PluginDescriptor;
059:        import org.java.plugin.registry.PluginElement;
060:        import org.java.plugin.registry.PluginFragment;
061:        import org.java.plugin.registry.UniqueIdentity;
062:        import org.java.plugin.util.ExtendedProperties;
063:        import org.java.plugin.util.IoUtil;
064:
065:        /**
066:         * This implementation of path resolver makes "shadow copy" of plug-in resources
067:         * before resolving paths to them, this helps avoid locking of local resources
068:         * and run native code from remote locations.
069:         * <p>
070:         * <b>Configuration parameters</b>
071:         * </p>
072:         * <p>
073:         * This path resolver implementation supports following configuration
074:         * parameters:
075:         * <dl>
076:         *   <dt>shadowFolder</dt>
077:         *   <dd>Path to the folder where to copy resources to prevent their locking. By
078:         *     default this will be
079:         *     <code>System.getProperty("java.io.tmpdir") + "/.jpf-shadow"</code>.
080:         *     Please note that this folder will be maintained automatically by the
081:         *     Framework and might be cleared without any confirmation or notification.
082:         *     So it is strongly not recommended to use plug-ins folder (or other
083:         *     sensitive application directory) as shadow folder, this may lead to
084:         *     losing your data.</dd>
085:         *   <dt>unpackMode</dt>
086:         *   <dd>If <code>always</code>, "JAR'ed" or "ZIP'ed" plug-ins will be
087:         *     un-compressed to the shadow folder, if <code>never</code>, they will be
088:         *     just copied, if <code>smart</code>, the processing depends on plug-in
089:         *     content - if plug-in contains JAR libraries, it will be un-packed,
090:         *     otherwise just copied to shadow folder. It is also possible to add
091:         *     boolean "unpack" attribute to plug-in manifest, in this case, it's value
092:         *     will be taken into account. The default parameter value is
093:         *     <code>smart</code>.</dd>
094:         * </dl>
095:         * </p>
096:         *
097:         * @version $Id: ShadingPathResolver.java,v 1.5 2007/05/13 16:31:48 ddimon Exp $
098:         */
099:        public class ShadingPathResolver extends StandardPathResolver {
100:            private static final String UNPACK_MODE_ALWAIS = "always"; //$NON-NLS-1$
101:            private static final String UNPACK_MODE_NEVER = "never"; //$NON-NLS-1$
102:            private static final String UNPACK_MODE_SMART = "smart"; //$NON-NLS-1$
103:
104:            private File shadowFolder;
105:            private String unpackMode;
106:            private Map<String, URL> shadowUrlMap = new HashMap<String, URL>(); // <pluginId or fragmentId, shadow URL>
107:            private Map<String, Boolean> unpackModeMap = new HashMap<String, Boolean>(); // <pluginId or fragmentId, Boolean>
108:            private ShadowDataController controller;
109:
110:            /**
111:             * @see org.java.plugin.PathResolver#configure(ExtendedProperties)
112:             */
113:            @Override
114:            public synchronized void configure(final ExtendedProperties config)
115:                    throws Exception {
116:                super .configure(config);
117:                String folder = config.getProperty("shadowFolder"); //$NON-NLS-1$
118:                if ((folder != null) && (folder.length() > 0)) {
119:                    try {
120:                        shadowFolder = new File(folder).getCanonicalFile();
121:                    } catch (IOException ioe) {
122:                        log.warn("failed initializing shadow folder " + folder //$NON-NLS-1$
123:                                + ", falling back to the default folder", ioe); //$NON-NLS-1$
124:                    }
125:                }
126:                if (shadowFolder == null) {
127:                    shadowFolder = new File(System
128:                            .getProperty("java.io.tmpdir"), //$NON-NLS-1$
129:                            ".jpf-shadow"); //$NON-NLS-1$
130:                }
131:                log.debug("shadow folder is " + shadowFolder); //$NON-NLS-1$
132:                if (!shadowFolder.exists()) {
133:                    shadowFolder.mkdirs();
134:                }
135:                unpackMode = config
136:                        .getProperty("unpackMode", UNPACK_MODE_SMART); //$NON-NLS-1$
137:                log.debug("unpack mode parameter value is " + unpackMode); //$NON-NLS-1$
138:                controller = ShadowDataController.init(shadowFolder,
139:                        buildFileFilter(config));
140:                log.info("configured, shadow folder is " + shadowFolder); //$NON-NLS-1$
141:            }
142:
143:            private FileFilter buildFileFilter(final ExtendedProperties config) {
144:                final FileFilter includesFilter;
145:                String patterns = config.getProperty("includes"); //$NON-NLS-1$
146:                if ((patterns != null) && (patterns.trim().length() > 0)) {
147:                    includesFilter = new RegexpFileFilter(patterns);
148:                } else {
149:                    includesFilter = null;
150:                }
151:                final FileFilter excludesFilter;
152:                patterns = config.getProperty("excludes"); //$NON-NLS-1$
153:                if ((patterns != null) && (patterns.trim().length() > 0)) {
154:                    excludesFilter = new RegexpFileFilter(patterns);
155:                } else {
156:                    excludesFilter = null;
157:                }
158:                if ((excludesFilter == null) && (includesFilter == null)) {
159:                    return null;
160:                }
161:                return new CombinedFileFilter(includesFilter, excludesFilter);
162:            }
163:
164:            /**
165:             * @see org.java.plugin.standard.StandardPathResolver#registerContext(
166:             *      org.java.plugin.registry.Identity, java.net.URL)
167:             */
168:            @Override
169:            public void registerContext(Identity idt, URL url) {
170:                super .registerContext(idt, url);
171:                Boolean mode;
172:                if (UNPACK_MODE_ALWAIS.equalsIgnoreCase(unpackMode)) {
173:                    mode = Boolean.TRUE;
174:                } else if (UNPACK_MODE_NEVER.equalsIgnoreCase(unpackMode)) {
175:                    mode = Boolean.FALSE;
176:                } else {
177:                    PluginDescriptor descr = null;
178:                    PluginFragment fragment = null;
179:                    if (idt instanceof  PluginDescriptor) {
180:                        descr = (PluginDescriptor) idt;
181:                    } else if (idt instanceof  PluginFragment) {
182:                        fragment = (PluginFragment) idt;
183:                        descr = fragment.getRegistry().getPluginDescriptor(
184:                                fragment.getPluginId());
185:                    } else if (idt instanceof  PluginElement) {
186:                        PluginElement<?> element = (PluginElement) idt;
187:                        descr = element.getDeclaringPluginDescriptor();
188:                        fragment = element.getDeclaringPluginFragment();
189:                    } else {
190:                        throw new IllegalArgumentException(
191:                                "unknown identity class " //$NON-NLS-1$
192:                                        + idt.getClass().getName());
193:                    }
194:                    mode = getUnpackMode(descr, fragment);
195:                }
196:                log.debug("unpack mode for " + idt + " is " + mode); //$NON-NLS-1$ //$NON-NLS-2$
197:                unpackModeMap.put(idt.getId(), mode);
198:            }
199:
200:            private Boolean getUnpackMode(final PluginDescriptor descr,
201:                    final PluginFragment fragment) {
202:                for (PluginAttribute attr : filterCollection(descr
203:                        .getAttributes("unpack"), fragment)) { //$NON-NLS-1$
204:                    return Boolean.valueOf("false".equalsIgnoreCase( //$NON-NLS-1$
205:                            attr.getValue()));
206:                }
207:                for (Library lib : filterCollection(descr.getLibraries(),
208:                        fragment)) {
209:                    if (lib.isCodeLibrary()
210:                            && (lib.getPath().toLowerCase(Locale.getDefault())
211:                                    .endsWith(".jar") //$NON-NLS-1$
212:                            || lib.getPath().toLowerCase(Locale.getDefault())
213:                                    .endsWith(".zip"))) { //$NON-NLS-1$
214:                        return Boolean.TRUE;
215:                    }
216:                }
217:                return Boolean.FALSE;
218:            }
219:
220:            private <T extends PluginElement<?>> Collection<T> filterCollection(
221:                    final Collection<T> coll, final PluginFragment fragment) {
222:                if (fragment == null) {
223:                    return coll;
224:                }
225:                LinkedList<T> result = new LinkedList<T>();
226:                for (T element : coll) {
227:                    if (fragment.equals(element.getDeclaringPluginFragment())) {
228:                        result.add(element);
229:                    }
230:                }
231:                return result;
232:            }
233:
234:            /**
235:             * @see org.java.plugin.standard.StandardPathResolver#unregisterContext(
236:             *      java.lang.String)
237:             */
238:            @Override
239:            public void unregisterContext(String id) {
240:                shadowUrlMap.remove(id);
241:                unpackModeMap.remove(id);
242:                super .unregisterContext(id);
243:            }
244:
245:            /**
246:             * @see org.java.plugin.PathResolver#resolvePath(
247:             *      org.java.plugin.registry.Identity, java.lang.String)
248:             */
249:            @Override
250:            public URL resolvePath(final Identity idt, final String path) {
251:                URL baseUrl;
252:                if (idt instanceof  PluginDescriptor) {
253:                    baseUrl = getBaseUrl((PluginDescriptor) idt);
254:                } else if (idt instanceof  PluginFragment) {
255:                    baseUrl = getBaseUrl((PluginFragment) idt);
256:                } else if (idt instanceof  PluginElement) {
257:                    PluginElement<?> element = (PluginElement) idt;
258:                    if (element.getDeclaringPluginFragment() != null) {
259:                        baseUrl = getBaseUrl(element
260:                                .getDeclaringPluginFragment());
261:                    } else {
262:                        baseUrl = getBaseUrl(element
263:                                .getDeclaringPluginDescriptor());
264:                    }
265:                } else {
266:                    throw new IllegalArgumentException(
267:                            "unknown identity class " //$NON-NLS-1$
268:                                    + idt.getClass().getName());
269:                }
270:                return resolvePath(baseUrl, path);
271:            }
272:
273:            protected synchronized URL getBaseUrl(final UniqueIdentity uid) {
274:                URL result = shadowUrlMap.get(uid.getId());
275:                if (result != null) {
276:                    return result;
277:                }
278:                result = controller.shadowResource(getRegisteredContext(uid
279:                        .getId()), uid.getUniqueId(), (unpackModeMap.get(uid
280:                        .getId())).booleanValue());
281:                shadowUrlMap.put(uid.getId(), result);
282:                return result;
283:            }
284:        }
285:
286:        final class ShadingUtil {
287:            static String getExtension(final String name) {
288:                if ((name == null) || (name.length() == 0)) {
289:                    return null;
290:                }
291:                int p = name.lastIndexOf('.');
292:                if ((p != -1) && (p > 0) && (p < name.length() - 1)) {
293:                    return name.substring(p + 1);
294:                }
295:                return null;
296:            }
297:
298:            static void unpack(final ZipFile zipFile, final File destFolder)
299:                    throws IOException {
300:                for (Enumeration<? extends ZipEntry> en = zipFile.entries(); en
301:                        .hasMoreElements();) {
302:                    ZipEntry entry = en.nextElement();
303:                    String name = entry.getName();
304:                    File entryFile = new File(destFolder.getCanonicalPath()
305:                            + "/" + name); //$NON-NLS-1$
306:                    if (name.endsWith("/")) { //$NON-NLS-1$
307:                        if (!entryFile.exists() && !entryFile.mkdirs()) {
308:                            throw new IOException(
309:                                    "can't create folder " + entryFile); //$NON-NLS-1$
310:                        }
311:                    } else {
312:                        File folder = entryFile.getParentFile();
313:                        if (!folder.exists() && !folder.mkdirs()) {
314:                            throw new IOException(
315:                                    "can't create folder " + folder); //$NON-NLS-1$
316:                        }
317:                        OutputStream out = new BufferedOutputStream(
318:                                new FileOutputStream(entryFile, false));
319:                        try {
320:                            InputStream in = zipFile.getInputStream(entry);
321:                            try {
322:                                IoUtil.copyStream(in, out, 1024);
323:                            } finally {
324:                                in.close();
325:                            }
326:                        } finally {
327:                            out.close();
328:                        }
329:                    }
330:                    entryFile.setLastModified(entry.getTime());
331:                }
332:            }
333:
334:            static void unpack(final InputStream strm, final File destFolder)
335:                    throws IOException {
336:                ZipInputStream zipStrm = new ZipInputStream(strm);
337:                ZipEntry entry = zipStrm.getNextEntry();
338:                while (entry != null) {
339:                    String name = entry.getName();
340:                    File entryFile = new File(destFolder.getCanonicalPath()
341:                            + "/" + name); //$NON-NLS-1$
342:                    if (name.endsWith("/")) { //$NON-NLS-1$
343:                        if (!entryFile.exists() && !entryFile.mkdirs()) {
344:                            throw new IOException(
345:                                    "can't create folder " + entryFile); //$NON-NLS-1$
346:                        }
347:                    } else {
348:                        File folder = entryFile.getParentFile();
349:                        if (!folder.exists() && !folder.mkdirs()) {
350:                            throw new IOException(
351:                                    "can't create folder " + folder); //$NON-NLS-1$
352:                        }
353:                        OutputStream out = new BufferedOutputStream(
354:                                new FileOutputStream(entryFile, false));
355:                        try {
356:                            IoUtil.copyStream(zipStrm, out, 1024);
357:                        } finally {
358:                            out.close();
359:                        }
360:                    }
361:                    entryFile.setLastModified(entry.getTime());
362:                    entry = zipStrm.getNextEntry();
363:                }
364:            }
365:
366:            static boolean deleteFile(final File file) {
367:                if (file.isDirectory()) {
368:                    IoUtil.emptyFolder(file);
369:                }
370:                return file.delete();
371:            }
372:
373:            static Date getLastModified(final URL url) throws IOException {
374:                long result = 0;
375:                if ("jar".equalsIgnoreCase(url.getProtocol())) { //$NON-NLS-1$
376:                    String urlStr = url.toExternalForm();
377:                    int p = urlStr.indexOf("!/"); //$NON-NLS-1$
378:                    if (p != -1) {
379:                        //sourceFile = IoUtil.url2file(new URL(urlStr.substring(4, p)));
380:                        return getLastModified(new URL(urlStr.substring(4, p)));
381:                    }
382:                }
383:                File sourceFile = IoUtil.url2file(url);
384:                if (sourceFile != null) {
385:                    result = sourceFile.lastModified();
386:                } else {
387:                    URLConnection cnn = url.openConnection();
388:                    try {
389:                        cnn.setUseCaches(false);
390:                        cnn.setDoInput(false); // this should force using HTTP HEAD method
391:                        result = cnn.getLastModified();
392:                    } finally {
393:                        try {
394:                            cnn.getInputStream().close();
395:                        } catch (IOException ioe) {
396:                            // ignore
397:                        }
398:                    }
399:                }
400:                if (result == 0) {
401:                    throw new IOException(
402:                            "can't retrieve modification date for resource " //$NON-NLS-1$
403:                                    + url);
404:                }
405:                // for some reason modification milliseconds for some files are unstable
406:                Calendar cldr = Calendar.getInstance(Locale.ENGLISH);
407:                cldr.setTime(new Date(result));
408:                cldr.set(Calendar.MILLISECOND, 0);
409:                return cldr.getTime();
410:            }
411:
412:            private static String getRelativePath(final File base,
413:                    final File file) throws IOException {
414:                String basePath;
415:                String filePath = file.getCanonicalPath();
416:                if (base.isFile()) {
417:                    File baseParent = base.getParentFile();
418:                    if (baseParent == null) {
419:                        return null;
420:                    }
421:                    basePath = baseParent.getCanonicalPath();
422:                } else {
423:                    basePath = base.getCanonicalPath();
424:                }
425:                if (!basePath.endsWith(File.separator)) {
426:                    basePath += File.separator;
427:                }
428:                int p = basePath.indexOf(File.separatorChar);
429:                String prefix = null;
430:                while (p != -1) {
431:                    String newPrefix = basePath.substring(0, p + 1);
432:                    if (!filePath.startsWith(newPrefix)) {
433:                        break;
434:                    }
435:                    prefix = newPrefix;
436:                    p = basePath.indexOf(File.separatorChar, p + 1);
437:                }
438:                if (prefix == null) {
439:                    return null;
440:                }
441:                filePath = filePath.substring(prefix.length());
442:                if (prefix.length() == basePath.length()) {
443:                    return filePath;
444:                }
445:                int c = 0;
446:                p = basePath.indexOf(File.separatorChar, prefix.length());
447:                while (p != -1) {
448:                    c++;
449:                    p = basePath.indexOf(File.separatorChar, p + 1);
450:                }
451:                for (int i = 0; i < c; i++) {
452:                    filePath = ".." + File.separator + filePath; //$NON-NLS-1$
453:                }
454:                return filePath;
455:            }
456:
457:            private static String getRelativeUrl(final File base,
458:                    final File file) throws IOException {
459:                String result = ShadingUtil.getRelativePath(base, file);
460:                if (result == null) {
461:                    return null;
462:                }
463:                result = result.replace('\\', '/');
464:                if (file.isDirectory() && !result.endsWith("/")) { //$NON-NLS-1$
465:                    result += "/"; //$NON-NLS-1$
466:                }
467:                return result;
468:            }
469:
470:            static String getRelativeUrl(final File base, final URL url)
471:                    throws IOException {
472:                File file = IoUtil.url2file(url);
473:                if (file != null) {
474:                    String result = getRelativeUrl(base, file);
475:                    if (result != null) {
476:                        return result;
477:                    }
478:                }
479:                if ("jar".equalsIgnoreCase(url.getProtocol())) { //$NON-NLS-1$
480:                    String urlStr = url.toExternalForm();
481:                    int p = urlStr.indexOf("!/"); //$NON-NLS-1$
482:                    if (p != -1) {
483:                        return "jar:" //$NON-NLS-1$
484:                                + getRelativeUrl(base, new URL(urlStr
485:                                        .substring(4, p)))
486:                                + urlStr.substring(p);
487:                    }
488:                }
489:                return url.toExternalForm();
490:            }
491:
492:            static URL buildURL(final URL base, final String url)
493:                    throws MalformedURLException {
494:                if (!url.toLowerCase(Locale.ENGLISH).startsWith("jar:")) { //$NON-NLS-1$
495:                    return new URL(base, url);
496:                }
497:                int p = url.indexOf("!/"); //$NON-NLS-1$
498:                if (p == -1) {
499:                    return new URL(base, url);
500:                }
501:                return new URL("jar:" //$NON-NLS-1$
502:                        + new URL(base, url.substring(4, p)).toExternalForm()
503:                        + url.substring(p));
504:            }
505:
506:            private ShadingUtil() {
507:                // no-op
508:            }
509:        }
510:
511:        final class ShadowDataController {
512:            private static final String META_FILE_NAME = ".meta"; //$NON-NLS-1$
513:
514:            private final Log log = LogFactory
515:                    .getLog(ShadowDataController.class);
516:            private final File shadowFolder;
517:            private final URL shadowFolderUrl;
518:            private final Properties metaData;
519:            private final DateFormat dtf = new SimpleDateFormat(
520:                    "yyyy-MM-dd HH:mm:ss"); //$NON-NLS-1$
521:            private final FileFilter fileFilter;
522:
523:            static ShadowDataController init(final File shadowFolder,
524:                    final FileFilter filter) throws IOException {
525:                ShadowDataController result = new ShadowDataController(
526:                        shadowFolder, filter);
527:                result.quickCheck();
528:                result.save();
529:                return result;
530:            }
531:
532:            private ShadowDataController(final File folder,
533:                    final FileFilter filter) throws IOException {
534:                shadowFolder = folder;
535:                fileFilter = filter;
536:                shadowFolderUrl = IoUtil.file2url(folder);
537:                File metaFile = new File(shadowFolder, META_FILE_NAME);
538:                metaData = new Properties();
539:                if (metaFile.isFile()) {
540:                    try {
541:                        InputStream in = new FileInputStream(metaFile);
542:                        try {
543:                            metaData.load(in);
544:                        } finally {
545:                            in.close();
546:                        }
547:                        if (log.isDebugEnabled()) {
548:                            log.debug("meta-data loaded from file " + metaFile); //$NON-NLS-1$
549:                        }
550:                    } catch (IOException ioe) {
551:                        log
552:                                .warn(
553:                                        "failed loading meta-data from file " + metaFile, ioe); //$NON-NLS-1$
554:                    }
555:                }
556:            }
557:
558:            private void save() {
559:                File metaFile = new File(shadowFolder, META_FILE_NAME);
560:                try {
561:                    OutputStream out = new FileOutputStream(metaFile, false);
562:                    try {
563:                        metaData.store(out,
564:                                "This is automatically generated file."); //$NON-NLS-1$
565:                    } finally {
566:                        out.close();
567:                    }
568:                    if (log.isDebugEnabled()) {
569:                        log.debug("meta-data saved to file " + metaFile); //$NON-NLS-1$
570:                    }
571:                } catch (IOException ioe) {
572:                    log
573:                            .warn(
574:                                    "failed saving meta-data to file " + metaFile, ioe); //$NON-NLS-1$
575:                }
576:            }
577:
578:            private void quickCheck() {
579:                File[] files = shadowFolder.listFiles(new ShadowFileFilter());
580:                for (File file : files) {
581:                    if (metaData.containsValue(file.getName())) {
582:                        continue;
583:                    }
584:                    if (ShadingUtil.deleteFile(file)) {
585:                        if (log.isDebugEnabled()) {
586:                            log.debug("deleted shadow file " + file); //$NON-NLS-1$
587:                        }
588:                    } else {
589:                        log.warn("can't delete shadow file " + file); //$NON-NLS-1$
590:                    }
591:                }
592:                Set<Object> uids = new HashSet<Object>();
593:                for (Map.Entry<Object, Object> entry : metaData.entrySet()) {
594:                    String key = (String) entry.getKey();
595:                    if (!key.startsWith("uid:")) { //$NON-NLS-1$
596:                        continue;
597:                    }
598:                    uids.add(entry.getValue());
599:                }
600:                for (Object object : uids) {
601:                    quickCheck((String) object);
602:                }
603:            }
604:
605:            private void quickCheck(final String uid) {
606:                if (log.isDebugEnabled()) {
607:                    log.debug("quick check of UID " + uid); //$NON-NLS-1$
608:                }
609:                String url = metaData.getProperty("source:" + uid, null); //$NON-NLS-1$
610:                String file = metaData.getProperty("file:" + uid, null); //$NON-NLS-1$
611:                String modified = metaData.getProperty("modified:" + uid, null); //$NON-NLS-1$
612:                if ((url == null) || (file == null) || (modified == null)) {
613:                    if (log.isDebugEnabled()) {
614:                        log.debug("meta-data incomplete, UID=" + uid); //$NON-NLS-1$
615:                    }
616:                    remove(uid);
617:                    return;
618:                }
619:                try {
620:                    if (!dtf.parse(modified).equals(
621:                            ShadingUtil.getLastModified(ShadingUtil.buildURL(
622:                                    shadowFolderUrl, url)))) {
623:                        if (log.isDebugEnabled()) {
624:                            log
625:                                    .debug("source modification detected, UID=" + uid //$NON-NLS-1$
626:                                            + ", source=" + url); //$NON-NLS-1$
627:                        }
628:                        remove(uid);
629:                    }
630:                } catch (IOException ioe) {
631:                    log.warn("quick check failed", ioe); //$NON-NLS-1$
632:                    remove(uid);
633:                } catch (ParseException pe) {
634:                    log.warn("quick check failed", pe); //$NON-NLS-1$
635:                    remove(uid);
636:                }
637:            }
638:
639:            private void remove(final String uid) {
640:                String file = metaData.getProperty("file:" + uid, null); //$NON-NLS-1$
641:                if (file != null) {
642:                    File lostFile = new File(shadowFolder, file);
643:                    if (ShadingUtil.deleteFile(lostFile)) {
644:                        if (log.isDebugEnabled()) {
645:                            log.debug("deleted lost file " + file); //$NON-NLS-1$
646:                        }
647:                    } else {
648:                        log.warn("can't delete lost file " + file); //$NON-NLS-1$
649:                    }
650:                }
651:                boolean removed = metaData.remove("uid:" + uid) != null; //$NON-NLS-1$
652:                removed |= metaData.remove("source:" + uid) != null; //$NON-NLS-1$
653:                removed |= metaData.remove("file:" + uid) != null; //$NON-NLS-1$
654:                removed |= metaData.remove("modified:" + uid) != null; //$NON-NLS-1$
655:                if (removed && log.isDebugEnabled()) {
656:                    log.debug("removed meta-data, UID=" + uid); //$NON-NLS-1$
657:                }
658:            }
659:
660:            private URL add(final String uid, final URL sourceUrl,
661:                    final File file, final Date modified) throws IOException {
662:                URL result = IoUtil.file2url(file);
663:                metaData.setProperty("uid:" + uid, uid); //$NON-NLS-1$
664:                String source = ShadingUtil.getRelativeUrl(shadowFolder,
665:                        sourceUrl);
666:                metaData.setProperty("source:" + uid, source); //$NON-NLS-1$
667:                metaData.setProperty("file:" + uid, file.getName()); //$NON-NLS-1$
668:                metaData.setProperty("modified:" + uid, dtf.format(modified)); //$NON-NLS-1$
669:                save();
670:                if (log.isDebugEnabled()) {
671:                    log.debug("shading done, UID=" + uid + ", source=" //$NON-NLS-1$ //$NON-NLS-2$
672:                            + source + ", file=" + result //$NON-NLS-1$
673:                            + ", modified=" + dtf.format(modified)); //$NON-NLS-1$
674:                }
675:                return result;
676:            }
677:
678:            URL shadowResource(final URL source, final String uid,
679:                    final boolean unpack) {
680:                try {
681:                    URL result = deepCheck(source, uid);
682:                    if (result != null) {
683:                        if (log.isDebugEnabled()) {
684:                            log.debug("got actual shaded resource, UID=" + uid //$NON-NLS-1$
685:                                    + ", source=" + source //$NON-NLS-1$
686:                                    + ", file=" + result); //$NON-NLS-1$
687:                        }
688:                        return result;
689:                    }
690:                } catch (Exception e) {
691:                    log.warn("deep check failed, UID=" + uid //$NON-NLS-1$
692:                            + ", URL=" + source, e); //$NON-NLS-1$
693:                    remove(uid);
694:                }
695:                Date lastModified;
696:                try {
697:                    lastModified = ShadingUtil.getLastModified(source);
698:                } catch (IOException ioe) {
699:                    log.error(
700:                            "shading failed, can't get modification date for " //$NON-NLS-1$
701:                                    + source, ioe);
702:                    return source;
703:                }
704:                File file = IoUtil.url2file(source);
705:                if ((file != null) && file.isDirectory()) {
706:                    // copy local folder to the shadow directory
707:                    try {
708:                        File rootFolder = new File(shadowFolder, uid);
709:                        IoUtil.copyFolder(file, rootFolder, true, true,
710:                                fileFilter);
711:                        return add(uid, source, rootFolder, lastModified);
712:                    } catch (IOException ioe) {
713:                        log.error("failed shading local folder " + file, ioe); //$NON-NLS-1$
714:                        return source;
715:                    }
716:                }
717:                try {
718:                    if ("jar".equalsIgnoreCase(source.getProtocol())) { //$NON-NLS-1$
719:                        String urlStr = source.toExternalForm();
720:                        int p = urlStr.indexOf("!/"); //$NON-NLS-1$
721:                        if (p == -1) {
722:                            p = urlStr.length();
723:                        }
724:                        URL jarFileURL = new URL(urlStr.substring(4, p));
725:                        if (!unpack) {
726:                            String ext = ShadingUtil.getExtension(jarFileURL
727:                                    .getFile());
728:                            if (ext == null) {
729:                                ext = "jar"; //$NON-NLS-1$
730:                            }
731:                            File shadowFile = new File(shadowFolder, uid + '.'
732:                                    + ext);
733:                            File sourceFile = IoUtil.url2file(jarFileURL);
734:                            InputStream in;
735:                            if (sourceFile != null) {
736:                                in = new BufferedInputStream(
737:                                        new FileInputStream(sourceFile));
738:                            } else {
739:                                in = jarFileURL.openStream();
740:                            }
741:                            try {
742:                                OutputStream out = new FileOutputStream(
743:                                        shadowFile, false);
744:                                try {
745:                                    IoUtil.copyStream(in, out, 1024);
746:                                } finally {
747:                                    out.close();
748:                                }
749:                            } finally {
750:                                in.close();
751:                            }
752:                            return add(uid, source, shadowFile, lastModified);
753:                        }
754:                        URLConnection cnn = null;
755:                        try {
756:                            File sourceFile = IoUtil.url2file(jarFileURL);
757:                            ZipFile zipFile;
758:                            if (sourceFile != null) {
759:                                zipFile = new ZipFile(sourceFile);
760:                            } else {
761:                                cnn = source.openConnection();
762:                                cnn.setUseCaches(false);
763:                                zipFile = ((JarURLConnection) cnn).getJarFile();
764:                            }
765:                            File rootFolder = new File(shadowFolder, uid);
766:                            try {
767:                                ShadingUtil.unpack(zipFile, rootFolder);
768:                            } finally {
769:                                zipFile.close();
770:                            }
771:                            return add(uid, source, rootFolder, lastModified);
772:                        } finally {
773:                            if (cnn != null) {
774:                                cnn.getInputStream().close();
775:                            }
776:                        }
777:                    }
778:                } catch (IOException ioe) {
779:                    log.error("failed shading URL connection " + source, ioe); //$NON-NLS-1$
780:                    return source;
781:                }
782:                String fileName = source.getFile();
783:                if (fileName == null) {
784:                    log.warn("can't get file name from resource " + source //$NON-NLS-1$
785:                            + ", shading failed"); //$NON-NLS-1$
786:                    return source;
787:                }
788:                String ext = ShadingUtil.getExtension(fileName);
789:                if (ext == null) {
790:                    log
791:                            .warn("can't get file name extension for resource " + source //$NON-NLS-1$
792:                                    + ", shading failed"); //$NON-NLS-1$
793:                    return source;
794:                }
795:                if (unpack && ("jar".equalsIgnoreCase(ext) //$NON-NLS-1$
796:                        || "zip".equalsIgnoreCase(ext))) { //$NON-NLS-1$
797:                    try {
798:                        InputStream strm = source.openStream();
799:                        File rootFolder = new File(shadowFolder, uid);
800:                        try {
801:                            ShadingUtil.unpack(strm, rootFolder);
802:                        } finally {
803:                            strm.close();
804:                        }
805:                        return add(uid, source, rootFolder, lastModified);
806:                    } catch (IOException ioe) {
807:                        log
808:                                .error(
809:                                        "failed shading packed resource " + source, ioe); //$NON-NLS-1$
810:                        return source;
811:                    }
812:                }
813:                try {
814:                    File shadowFile = new File(shadowFolder, uid + '.' + ext);
815:                    InputStream in = source.openStream();
816:                    try {
817:                        OutputStream out = new FileOutputStream(shadowFile,
818:                                false);
819:                        try {
820:                            IoUtil.copyStream(in, out, 1024);
821:                        } finally {
822:                            out.close();
823:                        }
824:                    } finally {
825:                        in.close();
826:                    }
827:                    return add(uid, source, shadowFile, lastModified);
828:                } catch (IOException ioe) {
829:                    log.error("failed shading resource file " + source, ioe); //$NON-NLS-1$
830:                    return source;
831:                }
832:            }
833:
834:            private URL deepCheck(final URL source, final String uid)
835:                    throws Exception {
836:                String url = metaData.getProperty("source:" + uid, null); //$NON-NLS-1$
837:                if (url == null) {
838:                    if (log.isDebugEnabled()) {
839:                        log.debug("URL not found in meta-data, UID=" + uid); //$NON-NLS-1$
840:                    }
841:                    remove(uid);
842:                    return null;
843:                }
844:                if (log.isDebugEnabled()) {
845:                    log.debug("URL found in meta-data, UID=" //$NON-NLS-1$
846:                            + uid + ", source=" + source //$NON-NLS-1$
847:                            + ", storedURL=" + url); //$NON-NLS-1$
848:                }
849:                URL storedSource = ShadingUtil.buildURL(shadowFolderUrl, url);
850:                if (!storedSource.equals(source)) {
851:                    if (log.isDebugEnabled()) {
852:                        log.debug("inconsistent URL found in meta-data, UID=" //$NON-NLS-1$
853:                                + uid + ", source=" + source //$NON-NLS-1$
854:                                + ", storedSource=" + storedSource); //$NON-NLS-1$
855:                    }
856:                    remove(uid);
857:                    return null;
858:                }
859:                String modified = metaData.getProperty("modified:" + uid, null); //$NON-NLS-1$
860:                if (modified == null) {
861:                    if (log.isDebugEnabled()) {
862:                        log
863:                                .debug("modification info not found in meta-data, UID=" //$NON-NLS-1$
864:                                        + uid);
865:                    }
866:                    remove(uid);
867:                    return null;
868:                }
869:                if (!ShadingUtil.getLastModified(source).equals(
870:                        dtf.parse(modified))) {
871:                    if (log.isDebugEnabled()) {
872:                        log.debug("source modification detected, UID=" + uid //$NON-NLS-1$
873:                                + ", source=" + source); //$NON-NLS-1$
874:                    }
875:                    remove(uid);
876:                    return null;
877:                }
878:                String fileStr = metaData.getProperty("file:" + uid, null); //$NON-NLS-1$
879:                if (fileStr == null) {
880:                    if (log.isDebugEnabled()) {
881:                        log
882:                                .debug("file info not found in meta-data, UID=" + uid); //$NON-NLS-1$
883:                    }
884:                    remove(uid);
885:                    return null;
886:                }
887:                File file = new File(shadowFolder, fileStr);
888:                if (!file.exists()) {
889:                    if (log.isDebugEnabled()) {
890:                        log.debug("shadow file not found, UID=" + uid //$NON-NLS-1$
891:                                + ", source=" + source //$NON-NLS-1$
892:                                + ", file=" + file); //$NON-NLS-1$
893:                    }
894:                    remove(uid);
895:                    return null;
896:                }
897:                File sourceFile = IoUtil.url2file(source);
898:                if ((sourceFile != null) && sourceFile.isDirectory()) {
899:                    IoUtil.synchronizeFolders(sourceFile, file, fileFilter);
900:                    if (log.isDebugEnabled()) {
901:                        log.debug("folders synchronized, UID=" + uid //$NON-NLS-1$
902:                                + ", srcFile=" + sourceFile //$NON-NLS-1$
903:                                + ", destFile=" + file); //$NON-NLS-1$
904:                    }
905:                } else {
906:                    if (log.isDebugEnabled()) {
907:                        log
908:                                .debug("source " + source + " (file is " + sourceFile //$NON-NLS-1$ //$NON-NLS-2$
909:                                        + ") is not local folder, " //$NON-NLS-1$
910:                                        + "skipping synchronization, UID=" + uid); //$NON-NLS-1$
911:                    }
912:                }
913:                return IoUtil.file2url(file);
914:            }
915:
916:            static class ShadowFileFilter implements  FileFilter {
917:                /**
918:                 * @see java.io.FileFilter#accept(java.io.File)
919:                 */
920:                public boolean accept(final File file) {
921:                    return !META_FILE_NAME.equals(file.getName());
922:                }
923:            }
924:        }
925:
926:        final class RegexpFileFilter implements  FileFilter {
927:            private final Pattern[] patterns;
928:
929:            RegexpFileFilter(final String str) {
930:                StringTokenizer st = new StringTokenizer(str, "|", false); //$NON-NLS-1$
931:                patterns = new Pattern[st.countTokens()];
932:                for (int i = 0; i < patterns.length; i++) {
933:                    String pattern = st.nextToken();
934:                    if ((pattern == null) || (pattern.trim().length() == 0)) {
935:                        continue;
936:                    }
937:                    patterns[i] = Pattern.compile(pattern.trim());
938:                }
939:            }
940:
941:            /**
942:             * @see java.io.FileFilter#accept(java.io.File)
943:             */
944:            public boolean accept(final File file) {
945:                for (int i = 0; i < patterns.length; i++) {
946:                    if (patterns[i] == null) {
947:                        continue;
948:                    }
949:                    if (patterns[i].matcher(file.getName()).matches()) {
950:                        return true;
951:                    }
952:                }
953:                return false;
954:            }
955:        }
956:
957:        final class CombinedFileFilter implements  FileFilter {
958:            private final FileFilter includesFilter;
959:            private final FileFilter excludesFilter;
960:
961:            CombinedFileFilter(final FileFilter includes,
962:                    final FileFilter excludes) {
963:                includesFilter = includes;
964:                excludesFilter = excludes;
965:            }
966:
967:            /**
968:             * @see java.io.FileFilter#accept(java.io.File)
969:             */
970:            public boolean accept(final File file) {
971:                if (includesFilter != null) {
972:                    if (includesFilter.accept(file)) {
973:                        return true;
974:                    }
975:                }
976:                if ((excludesFilter != null) && excludesFilter.accept(file)) {
977:                    return false;
978:                }
979:                return true;
980:            }
981:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.