blob: b0f3ce1f238a92dd392af0dde3588663838c5167 [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.ipojo.manipulator.store;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;
import java.util.jar.Manifest;
import org.apache.felix.ipojo.manipulator.ResourceStore;
import org.apache.felix.ipojo.manipulator.ResourceVisitor;
import org.apache.felix.ipojo.manipulator.store.mapper.FileSystemResourceMapper;
import org.apache.felix.ipojo.manipulator.store.mapper.IdentityResourceMapper;
import org.apache.felix.ipojo.manipulator.util.Metadatas;
import org.apache.felix.ipojo.manipulator.util.Streams;
import org.apache.felix.ipojo.metadata.Element;
/**
* A {@link DirectoryResourceStore} knows how to read and write
* resources from (to respectively) a File directory.
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class DirectoryResourceStore implements ResourceStore {
/**
* Source directory where bytecode is read.
*/
private File m_source;
/**
* Target directory.
*/
private File m_target;
/**
* The builder of the updated manifest.
*/
private ManifestBuilder m_manifestBuilder;
/**
* Original manifest to be updated.
*/
private Manifest m_manifest;
/**
* Location of the manifest file to update.
*/
private File m_manifest_file;
/**
* Resource Mapper.
*/
private ResourceMapper m_mapper = new FileSystemResourceMapper(new IdentityResourceMapper());
public DirectoryResourceStore(File source) {
this(source, source);
}
public DirectoryResourceStore(File source, File target) {
m_source = source;
m_target = target;
}
public void setResourceMapper(ResourceMapper mapper) {
m_mapper = new FileSystemResourceMapper(mapper);
}
public void setManifestBuilder(ManifestBuilder manifestBuilder) {
m_manifestBuilder = manifestBuilder;
}
public void setManifest(Manifest manifest) {
m_manifest = manifest;
}
public void setManifestFile(File manifestFile){
m_manifest_file = manifestFile;
}
public byte[] read(String path) throws IOException {
File resource = new File(m_source, m_mapper.internalize(path));
if (!resource.isFile()) {
throw new IOException("File '" + resource + "' is not found (for class " + path + ").");
}
return Streams.readBytes(new FileInputStream(resource));
}
public void accept(ResourceVisitor visitor) {
traverseDirectory(m_source, visitor);
}
private void traverseDirectory(File directory, ResourceVisitor visitor) {
for (File child : directory.listFiles()) {
if (child.isDirectory()) {
traverseDirectory(child, visitor);
} else {
visitor.visit(getRelativeName(child));
}
}
}
private String getRelativeName(File file) {
String relative = file.getPath().substring(m_source.getPath().length());
return m_mapper.externalize(relative);
}
public void open() throws IOException {
// Update the manifest
Manifest updated = m_manifestBuilder.build(m_manifest);
// Write it to disk
OutputStream os = new FileOutputStream(m_manifest_file);
try {
updated.write(os);
} finally {
Streams.close(os);
}
}
public void writeMetadata(Element metadata) {
m_manifestBuilder.addMetada(Collections.singletonList(metadata));
m_manifestBuilder.addReferredPackage(Metadatas.findReferredPackages(metadata));
}
public void write(String resourcePath, byte[] bytecode) throws IOException {
// Internalize the name
File resource = new File(m_target, m_mapper.internalize(resourcePath));
// Create intermediate directories if needed
if (!resource.getParentFile().exists()) {
resource.getParentFile().mkdirs();
}
FileOutputStream fos = new FileOutputStream(resource);
try {
fos.write(bytecode);
fos.flush();
} finally {
Streams.close(fos);
}
}
public void close() throws IOException {
// Nothing to do
}
}