View Javadoc

1   package net.sf.jpkgmk.prototype;
2   
3   import java.io.File;
4   import java.io.IOException;
5   import java.io.StringWriter;
6   import java.io.Writer;
7   import java.util.ArrayList;
8   import java.util.Collections;
9   import java.util.Comparator;
10  import java.util.Iterator;
11  import java.util.List;
12  
13  import net.sf.jpkgmk.AbstractFileCreatorAdapter;
14  import net.sf.jpkgmk.DefaultFileHandler;
15  import net.sf.jpkgmk.DuplicateEntryException;
16  import net.sf.jpkgmk.FileHandler;
17  import net.sf.jpkgmk.PackageException;
18  import net.sf.jpkgmk.PkgInfo;
19  import net.sf.jpkgmk.pkgmap.PkgMap;
20  import net.sf.jpkgmk.pkgmap.PkgMapEntry;
21  import net.sf.jpkgmk.pkgmap.PkgMapEntryHeader;
22  import net.sf.jpkgmk.util.FileUtil;
23  import net.sf.jpkgmk.util.VariableMap;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  
28  /**
29   * Pure java impl for the creation of a prototype which is normally done with "pkgproto" on unix.
30   * Used for "pkgmk" on unix
31   * 
32   * @author gommma (gommma AT users.sourceforge.net)
33   * @author Last changed by: $Author: gommma $
34   * @version $Revision: 2 $ $Date: 2008-08-20 21:14:19 +0200 (Mi, 20 Aug 2008) $
35   * @since 1.0
36   */
37  public class Prototype extends AbstractFileCreatorAdapter
38  {
39  	public static final String PROTOTYPE="prototype";
40  	private Log log = LogFactory.getLog(Prototype.class);
41  	private List<PrototypeEntry> prototypeEntryList = new ArrayList<PrototypeEntry>();
42  	
43  	/** 
44  	 * variableMap for creating the PkgMap entries later
45  	 */
46  	private VariableMap variableMap = new VariableMap();
47  
48  	
49  	/**
50  	 * Default constructor
51  	 */
52  	public Prototype() {
53  		super();
54  	}
55  
56  	
57  	public VariableMap getVariableMap() {
58  		return variableMap;
59  	}
60  
61  	public void setVariableMap(VariableMap variableMap) {
62  		this.variableMap = variableMap;
63  	}
64  
65  
66  	public void writeContent(Writer writer) throws IOException 
67  	{
68  		for(Iterator<PrototypeEntry> iter=this.prototypeEntryList.iterator(); iter.hasNext(); ) {
69  			PrototypeEntry entry = iter.next();
70  			writer.write(entry.getLine());
71  			writer.write(PkgInfo.LINE_SEPARATOR);
72  		}
73  		writer.flush();
74  	}
75  
76  
77      @Override
78  	public FileHandler getFileHandler(File targetDir) {
79  		DefaultFileHandler fileCreator = new DefaultFileHandler(targetDir, PROTOTYPE);
80  		return fileCreator;
81  	}
82  
83      
84  	/**
85  	 * Adds a prototype entry. Does <b>not</b> create the physical file yet
86  	 * @param entry New entry to add
87  	 */
88  	public void add(PrototypeEntry entry) {
89  		log.debug("Adding entry: " + entry);
90  		this.add(this.prototypeEntryList.size(), entry);
91  	}
92  
93  	/**
94  	 * Adds a prototype entry. Does <b>not</b> create the physical file yet
95  	 * @param insertIndex The index where to insert the given entry
96  	 * @param entry New entry to add
97  	 */
98  	public void add(int insertIndex, PrototypeEntry entry) {
99  		log.debug("Adding entry: " + entry + ", index=" + insertIndex);
100 		if(prototypeEntryList.contains(entry)) {
101 			int index = prototypeEntryList.indexOf(entry);
102 			Object existingPrototypeEntry = prototypeEntryList.get(index);
103 			throw new DuplicateEntryException("The prototype already contains an entry that equals the given one: existing='" + existingPrototypeEntry + "', given='" + entry + "'.");
104 		}
105 		else {
106 			/*boolean success = */prototypeEntryList.add(insertIndex, entry);
107 //			if(!success) {
108 //				throw new IllegalStateException("Failed to add entry to list. Entry=" + entry);
109 //			}
110 			
111 			variableMap.registerInVariablesMap(entry);
112 		}
113 	}
114 
115 
116 	public boolean remove(PrototypeEntry entry) {
117 		variableMap.unregisterFromVariablesMap(entry);
118 		return this.prototypeEntryList.remove(entry);
119 	}
120 	
121 	public boolean contains(PrototypeEntry entry) {
122 		return prototypeEntryList.contains(entry);
123 	}
124 
125 	/**
126 	 * @return Returs the list of prototype entries in the order they were added before
127 	 */
128 	public List<PrototypeEntry> getPrototypeEntryList()
129 	{
130 		return Collections.unmodifiableList(this.prototypeEntryList);
131 	}
132 	
133 	/**
134 	 * Creates the package which includes the creation of all files that contain to the package
135 	 * as well as the java object {@link PkgMap}. Note that the physical pkgmap file is not created.
136 	 * @param targetDir The directory where all target files are copied to/created in.
137 	 * @return The object representation {@link PkgMap} of the pkgmap file. 
138 	 * @throws IOException
139 	 */
140 	public PkgMap createPackage(File targetDir) throws IOException {
141 		// create files
142 		this.createFiles(targetDir);
143 		// Create the pkgmap java object
144 		PkgMap pkgMap = this.createPkgMap(targetDir);
145 		return pkgMap;
146 	}
147 
148 	
149 	/**
150 	 * @param targetDir The directory in which the physical files for the pkgMapEntries are located
151 	 * @return The result pkgmap object
152 	 */
153 	public PkgMap createPkgMap(File targetDir) {
154 		log.debug("<Entering> addPrototypeEntriesToPkgMap()");
155 
156 		PkgMap pkgMap = new PkgMap();
157 		
158 		List<PrototypeEntry> prototypeEntryList = this.getPrototypeEntryList();
159 		for(Iterator<PrototypeEntry> iter=prototypeEntryList.iterator(); iter.hasNext();) {
160 			PrototypeEntry entry = iter.next();
161 			
162 			try {
163 				// Create a pkgmap entry from the prototype entry
164 				List<PkgMapEntry> pkgMapEntryList = entry.createPkgMapEntry(targetDir, this.variableMap);
165 				if(pkgMapEntryList != null)
166 					pkgMap.addAll(pkgMapEntryList);
167 			}
168 			catch(Exception e) {
169 				throw new PackageException("Exception while creating pkgmap entry for prototype entry " + entry + ". " +
170 						"Make sure you created the physical files before creating the package via Prototype.createFiles().", e);
171 			}
172 		}
173 
174 		PkgMapEntryHeader header = createHeader(targetDir, pkgMap);
175 		pkgMap.setHeader(header);
176 
177 		return pkgMap;
178 	}
179 
180 	private PkgMapEntryHeader createHeader(File targetDir, PkgMap pkgMap) {
181 		// Create the header dynamically from the lines
182 		Integer numberOfParts = pkgMap.getNumberOfParts();
183 		Long maximumPartSize = FileUtil.getBlockCount(targetDir);
184 		return new PkgMapEntryHeader(numberOfParts, maximumPartSize);
185 	}
186 
187 
188 
189 	public void createFiles(File targetDir) throws IOException {
190 		if(!targetDir.isDirectory()) {
191 			throw new IllegalStateException("The given target dir '" + targetDir + "' does not exist.");
192 		}
193 		
194 		List<PrototypeEntry> prototypeEntryList = this.getPrototypeEntryList();
195 		for(Iterator<PrototypeEntry> iter=prototypeEntryList.iterator(); iter.hasNext();) {
196 			PrototypeEntry entry = iter.next();
197 			try {
198 				// Create the files for the entry
199 				entry.create(targetDir, this.variableMap);
200 			}
201 			catch(Exception e) {
202 				throw new PackageException("Exception while creating package. Failed to create files for prototype entry '" + entry + "'", e);
203 			}
204 		}
205 	}
206 
207 	
208 	public String toPrettyString()
209 	{
210 		StringBuffer sb = new StringBuffer();
211 		sb.append(getClass().getName()).append("[");
212 
213 		StringWriter writer = new StringWriter();
214 		try {
215 			this.writeContent(writer);
216 			sb.append("\n");
217 			sb.append(writer.toString());
218 			sb.append("\n");
219 		} catch (IOException e) {
220 			String msg = "Exception while creating pretty string";
221 			log.warn(msg, e);
222 			sb.append(msg);
223 		}
224 		
225 		sb.append("]");
226 		return sb.toString();
227 	}
228 	
229     @Override
230 	public String toString()
231 	{
232 		StringBuffer sb = new StringBuffer();
233 		sb.append(getClass().getName()).append("[");
234 		sb.append("prototypeEntryList=").append(prototypeEntryList);
235 		sb.append("]");
236 		return sb.toString();
237 	}
238 	
239 	
240 	/**
241 	 * Sorts the PrototypeEntryFile objects so that the directories are before all other entries
242 	 */
243 	protected static class PrototypeEntryFileSorter implements Comparator<PrototypeEntry>
244 	{
245 
246 		public int compare(PrototypeEntry arg0, PrototypeEntry arg1) {
247 			if(arg0 == null) {
248 				return -1;
249 			}
250 			if(arg1 == null) {
251 				return 1;
252 			}
253 			
254 			if(arg0.getType() == PrototypeEntryType.D) {
255 				if(arg1.getType() == PrototypeEntryType.D) {
256 					return 0;
257 				}
258 				else {
259 					return -1;
260 				}
261 			}
262 			else {
263 				if(arg1.getType() == PrototypeEntryType.D) {
264 					return 1;
265 				}
266 				else {
267 					return 0;
268 				}
269 			}
270 		}
271 		
272 	}
273 
274 }