Source code: com/dghda/module/ModulePathJarComponent.java
1 /* Copyright (C) 2001 Duane Griffin <duanegriffin@users.sourceforge.net>
2 This file is part of Kent.
3
4 Kent is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 Kent is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public
15 License along with Kent; see the file COPYING. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18 */
19
20 package com.dghda.module;
21
22 import java.io.*;
23 import java.util.*;
24 import java.util.jar.*;
25
26 /**
27 A module path jar component provides access to module providers in a jar file.
28 */
29 public class ModulePathJarComponent implements ModulePathComponent {
30
31 /** An implementation of a provider based on a jar file entry. */
32 protected class JarEntryProvider extends ModulePathComponent.Provider {
33
34 /** Create a new provider using the given entry. */
35 public JarEntryProvider (JarEntry entry) {
36 m_Entry = entry;
37 }
38
39 /** Returns the entry's name. */
40 public String getName() {
41 return m_Entry.getName();
42 }
43
44 /** Returns the entry's last modification time. */
45 public long getModified() {
46 return m_Entry.getTime();
47 }
48
49 /** Returns an input stream for reading the entry. */
50 public InputStream getInputStream() throws IOException {
51 return m_JarFile.getInputStream (m_Entry);
52 }
53
54 private JarEntry m_Entry;
55 }
56
57 /** An iterator over the contents of the jar file. */
58 protected class JarIterator implements Iterator {
59
60 /**
61 Create a new iterator.
62 @param updated True if only entries that are new or have been modified since the last scan are included.
63 */
64 public JarIterator (boolean updated, long lastScanned) {
65 m_Enum = m_JarFile.entries();
66 m_Updated = updated;
67 m_LastScanned = lastScanned;
68 m_Current = getNextEntry();
69 }
70
71 /** Returns true if there is another provider available. */
72 public boolean hasNext() {
73 return (m_Current != null);
74 }
75
76 /** Returns the next provider. */
77 public Object next() {
78
79 // Check we haven't gone past the last entry
80 if (m_Current == null)
81 throw new NoSuchElementException();
82
83 // Move on
84 JarEntry entry = m_Current;
85 m_Current = getNextEntry();
86
87 // Construct & return a provider
88 return new JarEntryProvider (m_Current);
89 }
90
91 /** Throws a UnsupportedOperationException exception. */
92 public void remove() {
93 throw new UnsupportedOperationException();
94 }
95
96 private JarEntry getNextEntry() {
97 JarEntry result = null;
98
99 // Grab the next entry
100 while (m_Enum.hasMoreElements()) {
101 JarEntry entry = (JarEntry) m_Enum.nextElement();
102
103 // Ignore directories
104 if (entry.isDirectory())
105 continue;
106
107 // Ignore files that don't end with .class
108 if (!entry.getName().endsWith (".class"))
109 continue;
110
111 // Check last scan time, if required
112 if (m_Updated && (m_LastScanned >= entry.getTime()))
113 continue;
114
115 // OK, use it
116 result = entry;
117 break;
118 }
119
120 return result;
121 }
122
123 private Enumeration m_Enum;
124 private boolean m_Updated;
125 private long m_LastScanned;
126 private JarEntry m_Current;
127 }
128
129 /** Create a new path component representing the specified jar file. */
130 public ModulePathJarComponent (String jarFile) throws InvalidPathException {
131 try {
132 m_File = new File (jarFile);
133 m_JarFile = new JarFile (jarFile);
134 } catch (FileNotFoundException exc) {
135 throw new InvalidPathException ("Could not find jar file", jarFile);
136 } catch (IOException exc) {
137 throw new InvalidPathException ("Invalid jar file", jarFile);
138 }
139 }
140
141 /**
142 Iterate over all providers in the jar file.
143 @param updated If true only new providers or ones which have been modified since the last scan will be returned.
144 */
145 public Iterator getProviders (boolean updated) {
146
147 // Check whether we should bother scanning the archive
148 if (updated && (m_Scanned >= m_File.lastModified())) {
149 return new ModulePathComponent.EmptyIterator();
150 } else {
151 long last = m_Scanned;
152 m_Scanned = (new Date()).getTime();
153 return new JarIterator (updated, last);
154 }
155 }
156
157 /** Returns the path to the jar file. */
158 public String getPath() {
159 return m_File.getName();
160 }
161
162 private File m_File;
163 private JarFile m_JarFile;
164 private long m_Scanned = 0;
165 }