/*******************************************************************************
* Copyright (c) May 18, 2011 Zend Technologies Ltd.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.zend.sdklib.internal.target;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.zend.sdklib.target.ITargetLoader;
import org.zend.sdklib.target.IZendTarget;
/**
* Default persistence layer for targets
*
* @author Roy, 2011
*/
public class UserBasedTargetLoader implements ITargetLoader {
private static final String PROPERTY = "target";
private static final String INI_EXTENSION = ".ini";
private static final String CONF_FILENAME = "conf";
private final File baseDir;
public UserBasedTargetLoader() {
this(getDefaultTargetsDirectory());
}
public UserBasedTargetLoader(File baseDir) {
this.baseDir = baseDir;
if (!baseDir.exists()) {
throw new IllegalStateException(MessageFormat.format("targets folder ''{0}'' does not exist", baseDir.getAbsolutePath()));
}
}
public static File getDefaultTargetsDirectory() {
final String property = System.getProperty("user.home");
final File userFolder = new File(property);
if (userFolder.exists()) {
final File targetsDir = new File(userFolder, ".zend" + File.separator + "targets");
if (!targetsDir.isDirectory()) {
targetsDir.mkdirs();
}
return targetsDir;
} else {
throw new IllegalStateException("error finding user home directory");
}
}
/*
* (non-Javadoc)
*
* @see
* org.zend.sdklib.target.ITargetLoader#add(org.zend.sdklib.target.IZendTarget
* )
*/
@Override
public IZendTarget add(IZendTarget target) {
if (target == null) {
throw new IllegalArgumentException("target is null");
}
TargetDescriptor descriptor = getTargetDescriptor(target);
if (descriptor != null) {
File conf = new File(descriptor.path, CONF_FILENAME);
if (conf.exists() && conf.length() == 0) {
return target;
} else {
throw new IllegalArgumentException("target already exists");
}
}
// create descriptor
descriptor = storeTargetDescriptor(target);
if (null == descriptor) {
return null;
}
File confFile = new File(descriptor.path, CONF_FILENAME);
try {
confFile.createNewFile();
confFile.setReadable(false, false);
confFile.setReadable(true, true);
FileOutputStream fos = new FileOutputStream(confFile);
target.store(fos);
fos.close();
} catch (IOException e1) {
return null;
}
return target;
}
/*
* (non-Javadoc)
*
* @see org.zend.sdklib.target.ITargetLoader#remove(org.zend.sdklib.target.
* IZendTarget)
*/
@Override
public IZendTarget remove(IZendTarget target) {
final File df = getDescriptorFile(target.getId());
TargetDescriptor d = loadTargetDescriptor(df);
if (null == d) {
throw new IllegalArgumentException(MessageFormat.format("cannot find target ''{0}''", target.getId()));
}
delete(d.path);
final boolean delete2 = delete(df);
if (!delete2) {
throw new IllegalArgumentException("error deleting data");
}
return target;
}
/*
* (non-Javadoc)
*
* @see org.zend.sdklib.target.ITargetLoader#update(org.zend.sdklib.target.
* IZendTarget)
*/
@Override
public IZendTarget update(IZendTarget target) {
if (target == null) {
throw new IllegalArgumentException("target is null");
}
if (target.isTemporary()) {
return target;
}
TargetDescriptor descriptor = getTargetDescriptor(target);
if (descriptor == null) {
throw new IllegalArgumentException("target does not exists");
}
File confFile = new File(descriptor.path, CONF_FILENAME);
if (confFile.exists()) {
confFile.delete();
try {
confFile.createNewFile();
confFile.setReadable(false, false);
confFile.setReadable(true, true);
} catch (IOException e) {
}
}
try {
FileOutputStream fos = new FileOutputStream(confFile);
target.store(fos);
fos.close();
} catch (IOException e1) {
return null;
}
return target;
}
/* (non-Javadoc)
* @see org.zend.sdklib.target.ITargetLoader#isAvailable(org.zend.sdklib.target.IZendTarget)
*/
@Override
public boolean isAvailable(IZendTarget target) {
if (target == null) {
throw new IllegalArgumentException("target is null");
}
TargetDescriptor descriptor = getTargetDescriptor(target);
return (descriptor != null);
}
/*
* (non-Javadoc)
*
* @see org.zend.sdklib.target.ITargetLoader#loadAll()
*/
@Override
public IZendTarget[] loadAll() {
File[] targets = baseDir.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return file.getName().endsWith(INI_EXTENSION) && file.isFile();
}
});
final ArrayList<IZendTarget> arrayList = new ArrayList<IZendTarget>(
targets.length);
targets = sortTargets(targets);
for (File file : targets) {
final TargetDescriptor d = loadTargetDescriptor(file);
if (d.isValid()) {
File confFile = new File(d.path, CONF_FILENAME);
try {
InputStream is = new FileInputStream(confFile);
final ZendTarget target = new ZendTarget();
target.load(is);
arrayList.add(target);
} catch (IOException e1) {
// skip target loading
}
}
}
return (IZendTarget[]) arrayList.toArray(new IZendTarget[arrayList
.size()]);
}
private TargetDescriptor storeTargetDescriptor(IZendTarget target) {
try {
final File file = getDescriptorFile(target.getId());
if (!file.createNewFile()) {
return null;
}
final TargetDescriptor targetDescriptor = new TargetDescriptor();
targetDescriptor.target = target.getId();
targetDescriptor.path = new File(baseDir, targetDescriptor.target);
final Properties properties = new Properties();
properties.put(PROPERTY, targetDescriptor.target);
properties.put("path", targetDescriptor.path.getAbsolutePath());
final FileOutputStream fileOutputStream = new FileOutputStream(file);
properties.store(fileOutputStream, "descriptor for target "
+ target.getId());
fileOutputStream.close();
targetDescriptor.path.mkdir();
return targetDescriptor.isValid() ? targetDescriptor : null;
} catch (IOException e) {
// can't be identified as valid target - ignore
return null;
}
}
private TargetDescriptor getTargetDescriptor(IZendTarget target) {
File df = getDescriptorFile(target.getId());
return loadTargetDescriptor(df);
}
private TargetDescriptor loadTargetDescriptor(File file) {
try {
if (!file.exists()) {
return null;
}
final Properties properties = new Properties();
final FileInputStream fileInputStream = new FileInputStream(file);
properties.load(fileInputStream);
final TargetDescriptor targetDescriptor = new TargetDescriptor();
targetDescriptor.target = properties.getProperty(PROPERTY);
targetDescriptor.path = new File(properties.getProperty("path"));
fileInputStream.close();
return targetDescriptor.isValid() ? targetDescriptor : null;
} catch (IOException e) {
// can't be identified as valid target - ignore
return null;
}
}
private File getDescriptorFile(String target) {
if (!target.endsWith(INI_EXTENSION)) {
target = target + INI_EXTENSION;
}
final File file = new File(baseDir, target);
return file;
}
private boolean delete(File file) {
if (file == null || !file.exists()) {
return true;
}
if (file.isDirectory()) {
String[] children = file.list();
for (int i = 0; i < children.length; i++) {
boolean result = delete(new File(file, children[i]));
if (!result) {
return false;
}
}
}
return file.delete();
}
/**
* Holds the name and path of a target
*/
public class TargetDescriptor {
/**
* Name of the target
*/
public String target;
/**
* Path of the target directory
*/
public File path;
public boolean isValid() {
return this.target != null && this.path.exists();
}
}
private File[] sortTargets(File[] targets) {
try {
List<File> result = new ArrayList<File>();
for (File file : targets) {
int[] fileId = getId(file);
if (result.size() == 0) {
result.add(file);
} else {
int index = -1;
for (File sorted : result) {
int[] sortedId = getId(sorted);
if (sortedId[0] > fileId[0]) {
index = result.indexOf(sorted);
break;
} else if (sortedId[0] == fileId[0]
&& sortedId[1] > fileId[1]) {
index = result.indexOf(sorted);
break;
}
}
if (index == -1) {
result.add(file);
} else {
result.add(index, file);
}
}
}
return result.toArray(new File[0]);
} catch (Exception e) {
return targets;
}
}
private int[] getId(File file) {
String name = file.getName();
int index = name.lastIndexOf('.');
name = name.substring(0, index);
index = name.lastIndexOf('_');
if (index != -1) {
String[] segments = name.split("_");
return new int[] { Integer.valueOf(segments[0]),
Integer.valueOf(segments[1]) };
}
return new int[] { Integer.valueOf(name), 0 };
}
}