/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.netsysit.policymanager;
import de.netsysit.controller.IResultValues;
import de.netsysit.controller.MethodResult;
import de.netsysit.model.ActionModel;
import de.netsysit.model.ActionTupel;
import de.netsysit.policymanager.Enums.*;
import de.netsysit.model.DataBaseModel;
import de.netsysit.model.PolicyModel;
import de.netsysit.model.PolicyReader;
import de.netsysit.model.ReceiverModel;
import de.netsysit.model.XMLPolicyReader;
import java.awt.Component;
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.beans.DefaultPersistenceDelegate;
import java.beans.XMLEncoder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertStore;
import java.security.cert.CertStoreException;
import java.security.cert.CertStoreParameters;
import java.security.cert.CertificateException;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import org.netsys.cms.CMSException;
import org.netsys.cms.CMSProcessable;
import org.netsys.cms.CMSProcessableByteArray;
import org.netsys.cms.CMSSignedData;
import org.netsys.cms.CMSSignedDataGenerator;
/**
* This class contains all the static methods which are used in the program.
* @author ducksoul
*/
public final class PolicyUtilities implements IResultValues {
private static Locale loc = new Locale("de", "DE");
private static DataBaseModel dbModel = PolicyManager.getPolicyModel();
private static ResourceBundle rb;
private static ResourceBundle mb;
private static String systemState;
private static boolean showWarnings = false;
private static JFileChooser fc = new JFileChooser();
private PolicyUtilities() {
}
/**
* This method shows a SaveFileDialog to choose the filepath to the file
* in which the database should be saved. The dialog won't be shown if
* there is alreade a filepath saved in the model.
* @return A String which contains the filepath of xml database
*/
public static String showSaveDialog() {
//fc.addChoosableFileFilter(new DBFileFilter());
if(dbModel.getFilePath() != null)
fc.setCurrentDirectory(new File(dbModel.getFilePath()));
if (fc.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
dbModel.setFilePath(fc.getSelectedFile().getAbsolutePath());
return fc.getSelectedFile().getAbsolutePath();
} else {
return null;
}
}
/**
* This method sets the static variable loc.
* @param loc The new Locale
*/
public static void setLoc(Locale loc) {
PolicyUtilities.loc = loc;
rb = ResourceBundle.getBundle("resources.PolicyManager", loc);
mb = ResourceBundle.getBundle("resources.Messages", loc);
}
/**
* This method returns the current ResourceBundle which contains the
* Strings of the components in the GUI.
* @return The actual ResourceBundle of PolicyManager
*/
public static ResourceBundle getResourceBundle() {
if (rb == null) {
rb = ResourceBundle.getBundle("resources.PolicyManager", loc);
return rb;
} else {
return rb;
}
}
/**
* This method returns the current ResourceBundle which contains the
* Strings of the messages that may be shown.
* @return The actual ResourceBundle with message translations
*/
public static ResourceBundle getMessageBundle() {
if (mb == null) {
mb = ResourceBundle.getBundle("resources.Messages", loc);
return mb;
} else {
return mb;
}
}
/**
* This method returns the ResourceBundle in which the Strings of the
* components of the specified window are saved.
* @param window A String with the name of the specified window
* @param locale A Locale
* @return The ResourceBundle which contains the Strings
*/
public static ResourceBundle loadLanguageProps(String window, Locale locale) {
ResourceBundle rb_temp = null;
try {
rb_temp = ResourceBundle.getBundle("resources." + window, locale);
} catch (MissingResourceException mre) {
System.out.println("Missing Resource Exception");
}
return rb_temp;
}
/**
* This method loads the specified File f into the DataBaseModel m
* @param f A File which contains a policy database
* @param m A DataBaseModel in which the data of the File should be saved
*/
public static void readPolicyFile(File f, DataBaseModel m) {
if (f == null) {
return;
}
PolicyReader pr = new XMLPolicyReader();
pr.loadPolicy(f, m);
}
/**
* This method creates a line of a label on the left side and another
* component on the right side which will be added to the forwarded
* Container cont.
* @param cont A Container in which the line should be placed
* @param gbl A GridBagLayout
* @param c1 A Label that will be placed on the left side
* @param c2 A Component that will be placed on the right side
* @param row The row in which the line should be added
*/
public static void createLine(Container cont,
GridBagLayout gbl,
JLabel c1,
Component c2,
int row) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.EAST;
gbc.gridx = 0;
gbc.gridy = row;
gbc.insets = new Insets(2, 2, 2, 5);
gbc.weightx = 0.5;
gbl.setConstraints(c1, gbc);
cont.add(c1);
if (c2 instanceof JScrollPane) {
gbc.fill = GridBagConstraints.BOTH;
gbc.gridheight = 3;
} else {
gbc.fill = GridBagConstraints.NONE;
}
gbc.anchor = GridBagConstraints.LINE_START;
gbc.gridx = 1;
gbc.gridy = row;
gbc.insets = new Insets(2, 2, 2, 2);
gbc.weightx = 0.5;
gbl.setConstraints(c2, gbc);
cont.add(c2);
}
/**
* This method creates a line of a label on the left side and another
* component on the right side which will be added to the forwarded
* Container cont. It allows to define the insets of the line.
* @param cont A Container in which the line should be placed
* @param gbl A GridBagLayout
* @param c1 A Label that will be placed on the left side
* @param c2 A Component that will be placed on the right side
* @param row The row in which the line should be added
* @param topspace space between c1 and c2 and the component above them
* @param bottomspace space between c1 and c2 and the component beneath them
*/
public static void createLine(Container cont,
GridBagLayout gbl,
JLabel c1,
Component c2,
int row,
int topspace,
int bottomspace) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.EAST;
gbc.gridx = 0;
gbc.gridy = row;
gbc.insets = new Insets(topspace, 2, bottomspace, 5);
gbc.weightx = 0.5;
gbl.setConstraints(c1, gbc);
cont.add(c1);
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.LINE_START;
gbc.gridx = 1;
gbc.gridy = row;
gbc.insets = new Insets(topspace, 2, bottomspace, 2);
gbc.weightx = 0.5;
gbl.setConstraints(c2, gbc);
cont.add(c2);
}
/**
* This method adds a component to a Container cont which will be anchored
* with GridBagConstraints.NORTHWEST (top-left).
* @param cont A container in which the component should be placed
* @param gbl gbl A GridBagLayout
* @param c A component that should be placed in the container
* @param row The row in which the component should be placed
* @param col The column in which the component should be placed
* @param last A boolean that determines if the component should fill all of the space left
*/
public static void addSwingCompWest(Container cont, GridBagLayout gbl, Component c, int row, int col, boolean last) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.gridx = col;
gbc.gridy = row;
gbc.weightx = 0.0;
gbc.insets = new Insets(2, 5, 2, 15);
gbc.gridheight = 1;
if (last) {
gbc.weighty = 1.0;
}
gbl.setConstraints(c, gbc);
cont.add(c);
}
/**
* This method creates a new ImageIcon out of the transmitted path.
* @param path A String which contains the path to the resource
* @return The generated ImageIcon
*/
public static ImageIcon createImageIcon(String path) {
java.net.URL imgURL = PolicyUtilities.class.getResource(path);
return new ImageIcon(imgURL);
}
/**
* This method transforms an int variable to a boolean variable. It returns
* false for every int except 1.
* @param i An int variable
* @return A boolean variable
*/
public static boolean intToBool(int i) {
return (i == 1);
}
/**
* This method transforms a boolean variable to an int variable. It returns
* 1 if the boolean is true, else 0.
* @param bool A boolean variable
* @return An int variable
*/
public static int boolToInt(boolean bool) {
if (bool) {
return 1;
} else {
return 0;
}
}
/**
* This method checks if the transferred PolicyModel fallback is a valid
* fallback for the transferred PolicyModel parent. Returns true if valid,
* else false
* @param parent A PolicyModel
* @param fallback A PolicyModel
* @return A Boolean which indicates if the PolicyModel is valid
*/
public static boolean isValidPolicyFallback(PolicyModel parent, PolicyModel fallback) {
Set<PolicyModel> set = new HashSet<PolicyModel>();
set.add(parent); // parent darf nicht auftauchen im zweig
for (PolicyModel policy = fallback; policy != null; policy = policy.getFallback()) {
if (policy.equals(policy.getFallback())) {
return false; // oder eine Exception werfen
}
if (!set.add(policy)) {
// policy gibt es bereits in dem set, also moegliche endlosschleife
return false;
}
}
return true;
}
/**
* This method checks is a PolicyModel parent is a parent-policy to the also
* transferred PolicyModel policy. It returns true if it is, else false.
* @param parent A PolicyModel
* @param policy A PolicyModel
* @return A boolean which indicates if the PolicyModel is parent
*/
public static boolean isParentPolicy(PolicyModel parent, PolicyModel policy) {
if(parent.getFallback() != null)
if(parent.getFallback().equals(policy))
return true;
return false;
}
/**
* This method returns the parent-policy of the transferred policy. If no
* policy exists it returns null.
* @param policy A PolicyModel of which the parent should be found
* @param policies A List which includes all the policies
* @return A PolicyModel which is the parent-policy or null
*/
public static PolicyModel getParentPolicy(PolicyModel policy, List<PolicyModel> policies) {
for(int i=0; i<policies.size(); i++) {
PolicyModel parent = policies.get(i);
PolicyModel fb = parent.getFallback();
if((fb != null) && (fb.equals(policy)))
return parent;
}
return null;
}
/**
* This method returns an integer with the next free id for a new
* application.
* @return An int with an id
*/
public static int getNewApplicationId() {
Set<Integer> appKeys = dbModel.getAppKeys();
int id = 0;
for (Integer i : appKeys) {
if (i.intValue() == id) {
id++;
} else {
return id;
}
}
return appKeys.size();
}
/**
* This method returns an integer with the next free id for a new
* receiverlist.
* @return An int with an id
*/
public static int getNewReceiverListId() {
Set<Integer> receiverListKeys = dbModel.getReceiverListKeys();
int id = 0;
for (Integer i : receiverListKeys) {
if (i.intValue() == id) {
id++;
} else {
return id;
}
}
return receiverListKeys.size();
}
/**
* This method returns an integer with the next free id for a new policy.
* @return An int with an id
*/
public static int getNewPolicyId() {
Set<Integer> policyKeys = null;
switch (dbModel.getActiveLevel()) {
case A:
policyKeys = dbModel.getPolicyAKeys();
break;
case C:
policyKeys = dbModel.getPolicyCKeys();
break;
case I:
policyKeys = dbModel.getPolicyIKeys();
break;
}
int id = 0;
for (Integer i : policyKeys) {
if (i.intValue() == id) {
id++;
} else {
return id;
}
}
return policyKeys.size();
}
/**
* This method returns an integer with the next free id for a new receiver.
* @return An int with an id
*/
public static int getNewReceiverId() {
List<ReceiverModel> receivers = dbModel.getCurrentReceiverList().getReceivers();
Set<Integer> receiverKeys = new TreeSet();
for (ReceiverModel rm : receivers) {
receiverKeys.add(rm.getId());
}
int id = 0;
for (Integer i : receiverKeys) {
if (i.intValue() == id) {
id++;
} else {
return id;
}
}
return receiverKeys.size();
}
/**
* This method sets the ranks of the policies which are stored in the
* transferred List. If the also transferred boolean refresh is true then
* the updated list will be stored in the DataBaseModel.
* @param list A List that includes the policies
* @param refresh A boolean
*/
public static void setPolicyRanks(List<PolicyModel> list, boolean refresh) {
int size = list.size();
int current = size;
for (int i = 0; i < size; i++) {
PolicyModel p = list.get(i);
if(getParentPolicy(p, list) == null) {
for(; p != null; p = p.getFallback()) {
p.setRank(current);
current--;
}
}
}
if(refresh) {
switch (dbModel.getActiveLevel()) {
case A:
list = dbModel.getAPolicies();
break;
case C:
list = dbModel.getCPolicies();
break;
case I:
list = dbModel.getIPolicies();
break;
}
}
Collections.sort(list);
Collections.reverse(list);
}
/**
* This method creates an XML-String out of the DataBaseModel
* @return A String
*/
public static String createSystemStateString(DataBaseModel model) {
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
XMLEncoder xmlEncoder = new XMLEncoder(outputStream);
xmlEncoder.setPersistenceDelegate(ActionModel.class, new DefaultPersistenceDelegate(new String[]{"actions","id"}));
xmlEncoder.setPersistenceDelegate(ActionTupel.class, new DefaultPersistenceDelegate(new String[]{"algorithm","mode"}));
xmlEncoder.writeObject(model);
xmlEncoder.close();
outputStream.close();
return outputStream.toString();
} catch (IOException ex) {
Logger.getLogger(PolicyUtilities.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
/**
* This method checks if the systemState has been changed. Returns true if it
* has, else false.
* @return A boolean variable
*/
public static boolean isStateChanged() {
String newState = createSystemStateString(dbModel);
boolean changed = !systemState.equals(newState);
return changed;
}
public static void setSystemState(String state) {
PolicyUtilities.systemState = state;
}
/**
* This message shows a MessageDialog.
* @param message A String that contains the message
* @param type A JOptionPane.MessageType
* @return An int variable with the result of the dialog
*/
public static int showMessageDialog(String message, int type) {
int i = -1;
switch (type) {
case JOptionPane.WARNING_MESSAGE:
JOptionPane.showMessageDialog(null, message, rb.getString("warning"), JOptionPane.WARNING_MESSAGE);
break;
case JOptionPane.ERROR_MESSAGE:
JOptionPane.showMessageDialog(null, message, rb.getString("error"), JOptionPane.ERROR_MESSAGE);
break;
case JOptionPane.INFORMATION_MESSAGE:
JOptionPane.showMessageDialog(null, message, rb.getString("information"), JOptionPane.INFORMATION_MESSAGE);
break;
case JOptionPane.QUESTION_MESSAGE:
i = JOptionPane.showConfirmDialog(null, message, rb.getString("warning"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
break;
}
return i;
}
/**
* This method sets the boolean "show" which indicates if warnings should be
* displayed or not.
* @param show A boolean variable
*/
public static void setShowWarnings(boolean show) {
showWarnings = show;
}
/**
* This method returns a boolean which indicates if warnings should be shown
* or not. Returns true if warnings should be shown, else false.
* @return A boolean variable
*/
public static boolean isShowWarnings() {
return showWarnings;
}
/**
* This method replaces placeholders in messages with content.
* @param replace A String which contains the content.
* @param message A String with the message that contains the placeholder.
* @return A String containing the message with replaced content
*/
public static String replacePlaceHolder(String replace, String message) {
String str2 = message.replaceFirst("<placeholder>", replace);
return str2;
}
/**
* This method returns a PolicyModel which only is used to display that
* no policy has been selected. It will not be saved in the database.
* @return A PolicyModel
*/
public static PolicyModel getDummyPolicy() {
PolicyModel dummy = new PolicyModel();
dummy.setName(rb.getString("nopolicy"));
dummy.setId(13377331);
return dummy;
}
public static MethodResult sign(byte[] data2beSigned,
String keyStorePath,
char[] keyStorePassword,
String keyAlias,
char[] privateKeyPassword,
String digestOID) {
KeyStore keyStore = null;
Key privateKey;
CMSSignedDataGenerator generator;
CMSProcessable processableData;
CMSSignedData signedContainer;
MethodResult loadingKeyStoreResult;
MethodResult signingDataResult;
byte[] signedData = null;
int resultValue = UNKNOWN_ERROR;
Throwable th = null;
loadingKeyStoreResult = loadKeyStore(keyStorePath, keyStorePassword);
// Log.d(TAG, "keystore: " + loadingKeyStoreResult.getResultObject());
if (loadingKeyStoreResult.getResultValue() == OPERATION_SUCCESSFUL) {
try {
keyStore = (KeyStore) loadingKeyStoreResult.getResultObject();
privateKey = keyStore.getKey(keyAlias, privateKeyPassword);
generator = new CMSSignedDataGenerator();
generator.addSigner((PrivateKey) privateKey,
(X509Certificate) keyStore.getCertificate(keyAlias),
digestOID);
List<X509Certificate> certList = new ArrayList<X509Certificate>();
certList.add((X509Certificate) keyStore.getCertificate(keyAlias));
CertStoreParameters params = new CollectionCertStoreParameters(certList);
CertStore cs = CertStore.getInstance("Collection", params, "BC");
generator.addCertificatesAndCRLs(cs);
processableData = new CMSProcessableByteArray(data2beSigned);
signedContainer = generator.generate(processableData, true, "BC");
signedData = signedContainer.getEncoded();
resultValue = OPERATION_SUCCESSFUL;
} catch (UnrecoverableKeyException uke) {
uke.printStackTrace();
resultValue = PRIVATE_KEY_CORRUPTED;
th = uke;
} catch (KeyStoreException kse) {
kse.printStackTrace();
resultValue = KEYSTORE_CORRUPTED;
th = kse;
} catch (NoSuchAlgorithmException nsae) {
nsae.printStackTrace();
resultValue = ALGORITHM_NOT_FOUND;
th = nsae;
} catch (InvalidAlgorithmParameterException iape) {
iape.printStackTrace();
resultValue = ALGORITHM_NOT_FOUND;
th = iape;
} catch (NoSuchProviderException nspe) {
nspe.printStackTrace();
resultValue = CRYPTO_PROVIDER_NOT_FOUND;
th = nspe;
} catch (CertStoreException cse) {
cse.printStackTrace();
resultValue = CERTIFICATE_CORRUPTED;
th = cse;
} catch (CMSException cmse) {
cmse.printStackTrace();
resultValue = MESSAGE_CORRUPTED;
th = cmse;
} catch (IOException ioe) {
ioe.printStackTrace();
resultValue = IO_ERROR;
th = ioe;
} catch (Throwable t) {
t.printStackTrace();
resultValue = UNKNOWN_ERROR;
th = t;
}
}
else { // loading of keystore was not successful...
resultValue = loadingKeyStoreResult.getResultValue();
th = loadingKeyStoreResult.getT();
}
signingDataResult = new MethodResult(resultValue, signedData, th);
return signingDataResult;
}
private static MethodResult loadKeyStore(String keyStorePath, char[] keyStorePassword) {
MethodResult result;
int resultValue = UNKNOWN_ERROR;
Throwable th = null;
MethodResult gettingKeyStoreContentResult;
File keyStoreFile;
InputStream signedKeyStoreInputStream;
KeyStore keyStore = null;
try {
keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStoreFile = new File(keyStorePath);
signedKeyStoreInputStream = new FileInputStream(keyStoreFile);
gettingKeyStoreContentResult = getContentOfSignedData(signedKeyStoreInputStream, true);
if (gettingKeyStoreContentResult.getResultValue() == OPERATION_SUCCESSFUL) {
keyStore.load((InputStream) gettingKeyStoreContentResult.getResultObject(), keyStorePassword);
// XXX close the inputstream possible after loading the keystore ?
// Log.d(TAG, "keystore: " + keyStore);
resultValue = OPERATION_SUCCESSFUL;
}
else {
resultValue = gettingKeyStoreContentResult.getResultValue();
th = gettingKeyStoreContentResult.getT();
}
} catch (KeyStoreException kse) {
kse.printStackTrace();
resultValue = KEYSTORE_CORRUPTED;
th = kse;
} catch (FileNotFoundException fne) {
fne.printStackTrace();
resultValue = KEYSTORE_NOT_FOUND;
th = fne;
} catch (NoSuchAlgorithmException nsae) {
nsae.printStackTrace();
resultValue = ALGORITHM_NOT_FOUND;
th = nsae;
} catch (CertificateException ce) {
ce.printStackTrace();
resultValue = CERTIFICATE_CORRUPTED;
th = ce;
} catch (IOException ioe) {
ioe.printStackTrace();
resultValue = IO_ERROR;
th = ioe;
} catch (Throwable t) {
t.printStackTrace();
resultValue = UNKNOWN_ERROR;
th = t;
}
result = new MethodResult(resultValue, keyStore, th);
return result;
}
public static MethodResult getContentOfSignedData (InputStream signedContentStream, boolean resultAsStream) {
MethodResult result = null;
int resultValue = 0;
byte[] content = null;
Throwable th = null;
CMSSignedData signedData;
ByteArrayInputStream contentStream = null;
try {
signedData = new CMSSignedData(signedContentStream);
content = (byte[]) signedData.getSignedContent().getContent();
if (resultAsStream)
contentStream = new ByteArrayInputStream(content);
resultValue = OPERATION_SUCCESSFUL;
} catch (CMSException cmse) {
cmse.printStackTrace();
resultValue = MESSAGE_CORRUPTED;
th = cmse;
} catch (Throwable t) {
t.printStackTrace();
resultValue = UNKNOWN_ERROR;
th = t;
}
if (resultAsStream)
result = new MethodResult(resultValue, contentStream, th);
else
result = new MethodResult(resultValue, content, th);
return result;
}
}