blob: c7c15a6f62477d53e0c9fb6ec43bbc1899d5fa07 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.felix.inventory.impl.helper;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Locale;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.felix.inventory.Format;
import org.apache.felix.inventory.impl.InventoryPrinterHandler;
/**
* The ZIP configuration writer creates a zip with
* - txt output of a inventory printers (if supported)
* - json output of a inventory printers (if supported)
* - attachments from a inventory printer (if supported)
*/
public class ZipConfigurationWriter extends ConfigurationWriter
{
private final ZipConfigurationWriter.ConfigZipOutputStream zip;
private int entryCounter;
public static ZipConfigurationWriter create(final OutputStream out) throws IOException
{
final ZipConfigurationWriter.ConfigZipOutputStream zip = new ConfigZipOutputStream(out)
{
};
zip.setLevel(Deflater.BEST_SPEED);
zip.setMethod(ZipOutputStream.DEFLATED);
return new ZipConfigurationWriter(zip);
}
private ZipConfigurationWriter(final ZipConfigurationWriter.ConfigZipOutputStream zip) throws IOException
{
super(new OutputStreamWriter(zip, "UTF-8"));
this.zip = zip;
this.entryCounter = -1;
}
public void finish() throws IOException
{
this.zip.finish();
}
/**
* Overwrites the
* {@link ConfigurationWriter#printInventory(Format, InventoryPrinterHandler)}
* method writing the plain text output, the JSON output and any
* attachements to the ZIP file. The {@code format} argument is ignored.
*
* @param formatIgnored Ignored, may be {@code null}.
* @param handler The handler to be called to generate the output
*
* @throws IOException if an error occurrs writing to the ZIP file.
*/
public void printInventory(final Format formatIgnored, final InventoryPrinterHandler handler)
throws IOException
{
final String baseName = getBaseName(handler);
this.zip.handler(handler);
// print the plain text output
if (handler.supports(Format.TEXT))
{
final ZipEntry entry = new ZipEntry(baseName.concat(".txt"));
entry.setTime(System.currentTimeMillis());
this.zip.putNextEntry(entry, Format.TEXT);
handler.print(this, Format.TEXT, true);
this.flush();
this.zip.closeEntry();
}
// print the JSON format output
if (handler.supports(Format.JSON))
{
final ZipEntry entry = new ZipEntry("json/" + baseName + ".json");
entry.setTime(System.currentTimeMillis());
this.zip.putNextEntry(entry, Format.JSON);
handler.print(this, Format.JSON, true);
this.flush();
this.zip.closeEntry();
}
// any attachements from the handler
this.zip.attachements();
handler.addAttachments(this.zip, baseName.concat("/"));
this.zip.endAttachements();
this.zip.endHandler();
}
private String getBaseName(final InventoryPrinterHandler handler)
{
final String title = handler.getTitle();
final StringBuffer name = new StringBuffer(title.length());
for (int i = 0; i < title.length(); i++)
{
char c = title.charAt(i);
if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
{
name.append(c);
}
else
{
name.append('_');
}
}
this.entryCounter++;
return MessageFormat.format("{0,number,000}_{1}", new Object[]
{ new Integer(this.entryCounter), name });
}
private static class ConfigZipOutputStream extends ZipOutputStream
{
private final SimpleJson json;
ConfigZipOutputStream(final OutputStream out)
{
super(out);
this.json = new SimpleJson();
this.json.object();
// timestamp in the "created" object
final Date now = new Date();
final String nowFormatted = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.US)
.format(now);
this.json.key("created");
this.json.object();
this.json.key("date").value(nowFormatted);
this.json.key("stamp").value(String.valueOf(now.getTime()));
this.json.endObject();
// output from the printers in the "files" object
this.json.key("files").object();
}
void handler(final InventoryPrinterHandler handler)
{
this.json.key(handler.getName());
this.json.object();
this.json.key("title").value(handler.getTitle());
}
void endHandler()
{
this.json.endObject();
}
void attachements()
{
this.json.key("attachements");
this.json.array();
}
void endAttachements()
{
this.json.endArray();
}
void putNextEntry(ZipEntry e, Format format) throws IOException
{
this.json.key(format.toString().toLowerCase());
this.putNextEntry(e);
}
public void putNextEntry(ZipEntry e) throws IOException
{
this.json.value(e.getName());
super.putNextEntry(e);
}
public void finish() throws IOException
{
// end "files" and root objects
this.json.endObject().endObject();
final ZipEntry entry = new ZipEntry("index.json");
entry.setTime(System.currentTimeMillis());
super.putNextEntry(entry); // don't write the index to the JSON
this.write(this.json.toString().getBytes("UTF-8"));
this.flush();
this.closeEntry();
super.finish();
}
}
}