Eclipse custom perspective changed approach Kepler to Mars - java

I am updating an existing working RCP 3 app from
Kepler to Mars. It was written by another guy so having to learn a lot about RCP as I go.
What worked in Kepler was this:
public class ShowSelectViewDialogHandler extends DialogHandler {
/**
* The name of the parameter providing the view identifier.
*/
private static final String VIEW_ID_COMMAND_PARAMETER_NAME = "org.eclipse.ui.views.showView.viewId"; //$NON-NLS-1$
private static final String MAKE_FAST_COMMAND_PARAMETER_NAME = "org.eclipse.ui.views.showView.makeFast"; //$NON-NLS-1$
private final IHandler handler;
/**
* Creates a new ShowViewHandler that will open the view in its default location.
*/
public ShowSelectViewDialogHandler (final IHandler handler) {
this.handler = handler;
}
#Override
public final Object execute(final ExecutionEvent event) throws ExecutionException {
Object result = null;
IWorkbenchWindow window = EDMUIApplication.instance().getWorkbenchAdvisor().getWorkbenchWindowAdvisor().getWindow();
Map<String, String> parameters = event.getParameters();
String viewId = parameters.get(ShowSelectViewDialogHandler.VIEW_ID_COMMAND_PARAMETER_NAME);
String makeFast = parameters.get(ShowSelectViewDialogHandler.MAKE_FAST_COMMAND_PARAMETER_NAME);
if (viewId == null) {
ShowViewDialog dialog = new ShowViewDialog(window, new EDMUIViewRegistry(EDMUIConstants.CATEGORY_IDS));
if (dialog.open() == Window.OK) {
for (IViewDescriptor viewDescriptor : dialog.getSelection()) {
result = this.openView(window, viewDescriptor.getId(), makeFast);
}
}
} else {
result = this.openView(window, viewId, makeFast);
}
return result;
}
/**
* Opens the view with the given ID.
*
* #param window - workbench window of the view.
* #param viewId - id of the view to open.
* #param makeFast - command parameter.
* #return result of the handler execution.
* #throws ExecutionException - if default handler execution fails.
*/
private Object openView(final IWorkbenchWindow window, final String viewId, final String makeFast) throws ExecutionException {
Object result = null;
try {
Parameterization[] parameterization = this.createParameterization(viewId, makeFast, IWorkbenchCommandConstants.VIEWS_SHOW_VIEW);
result = this.executeDefaultHandler(this.handler, window, parameterization, IWorkbenchCommandConstants.VIEWS_SHOW_VIEW);
} catch (NotDefinedException ex) {
throw new ExecutionException(ex.getMessage(), ex);
}
return result;
}
/**
* Creates parameterization for the command.
*
* #param viewId - view id parameter value.
* #param makeFast - make fast parameter value.
* #param commandId - id of the command.
* #return created parameterization.
* #throws NotDefinedException - if there is no such parameter.
*/
private Parameterization[] createParameterization(final String viewId, final String makeFast, final String commandId) throws NotDefinedException {
ICommandService commandService = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class);
Command command = commandService.getCommand(IWorkbenchCommandConstants.VIEWS_SHOW_VIEW);
IParameter viewIdParameter = command.getParameter(ShowSelectViewDialogHandler.VIEW_ID_COMMAND_PARAMETER_NAME);
IParameter makeFastParameter = command.getParameter(ShowSelectViewDialogHandler.MAKE_FAST_COMMAND_PARAMETER_NAME);
return new Parameterization[] { new Parameterization(viewIdParameter, viewId), new Parameterization(makeFastParameter, makeFast) };
}
But now ShowViewDialog signature has changed. Also the original author made the statement that his approach was based on ShowViewHandler and there must be a better more standard way of achieving the same affect, i.e. controlling the display of our reduced set of views.
Any ideas on how to achieve this? There might be a tutorial somewhere, I found the Vogella one, but it is fairly general.

ShowViewDialog is an internal dialog so it should not have been used in the first place. As you have found internal dialogs can be changed without warning.
It looks like your code is using your own implementation of IViewRegistry. To stick to using only official APIs you would have to write your own version of the show view dialog. This is a fairly simple dialog using FilteredTree and the IViewRegistry getCategories and getViews methods.
There isn't a more standard way of doing this.

Related

Why does my imported Maven project throw incompatible type error when the types match exactly?

I am trying to call this method in my main project which is being imported using Maven
public void updateCreoParams(ComponentFeat compFeat, Model model)
But when I call it like (1) it throws an error on build (2)
(1)creoParams.updateCreoParams(compFeat, null);
compFeat is of the type ComponentFeat
(2)Error:(216, 61) java: incompatible types: com.ptc.pfc.pfcComponentFeat.ComponentFeat cannot be converted to java.util.List<[package].Parameter>
List is a variable that is set for the class in the constructor, if that makes a difference.
Any help would be appreciated.
Thank You
UPDATE
Here is the Class that is causing the issue. I expect it to work but for some reason the error above is thrown on build, even though the method being called doesnt take List as a parameter
public class CreoParameters {
ArrayList<String> parameterList;
List<Parameter> params;
/**
* Initialize this object with a list of parameters that you want to put onto the model
* #param params
*/
public CreoParameters(List<Parameter> params){
this.params = params;
parameterList = new ArrayList<String>();
for(int i=0; i<params.size(); i++){
parameterList.add(params.get(i).parameterName);
}
}
/**
* Updates the Parameters in Creo for a given assembly component, and a list of Params
* #param compFeat
* #param model
* #author jcesson
*/
public void updateCreoParams(ComponentFeat compFeat, Model model) {
try {
ParameterOwner modelToUpdate;
if(compFeat != null) {
modelToUpdate = compFeat;
}else if(model != null){
modelToUpdate = model;
}else{
modelToUpdate = null;
return;
}
//Removes old instance of Parameters to be updated
Parameters oldParams = modelToUpdate.ListParams();
for(int i=0; i<oldParams.getarraysize(); i++) {
String oldParamName = oldParams.get(i).GetName();
if(parameterList.contains(oldParamName)) {
oldParams.get(i).Delete();
}
}
oldParams.clear();
//Adds in the new Parameters
for(int i=0; i<params.size(); i++) {
ParamValue newPV = pfcModelItem.CreateStringParamValue(params.get(i).getParameterValue());
modelToUpdate.CreateParam(params.get(i).getParameterName(), newPV);
}
} catch (jxthrowable e) {
CEWSLogger.info("Bad Creo Model Error "+e.toString());
}
}
}
this is how it is called, and where the error is thrown upon build
neither updatedParams or compFeat are null.
private List<Parameter> updatedParams = new ArrayList<Parameter>();
private ComponentFeat compFeat;
.
.
.
CreoParameters creoParams = new CreoParameters(updatedParams);
creoParams.updateCreoParams(compFeat, null);
If anyone else runs into this problem, it is because of Maven. The Parameters used to include List after updating code an mvn clean was required, thats why when it built it didn't work but the compiler didn't throw any errors. After an mvn clean everything worked as it was supposed to

Spring-boot No thread-bound request found when throw exception on JMS queue listener

I am trying to consume an AWS queue using Spring boot with JMS, and I am having a problem throwing exceptions in my consumer method.
Every time I try to throw a custom exception in my consumer method, to log into an Aspect, the following message is returned:
errorCause=java.lang.IllegalStateException: No thread-bound request
found: Are you referring to request attributes outside of an actual
web request, or processing a request outside of the originally
receiving thread? If you are actually operating within a web request
and still receive this message, your code is probably running outside
of DispatcherServlet/DispatcherPortlet: In this case, use
RequestContextListener or RequestContextFilter to expose the current
request., errorMessage=Error listener queue,
date=2018-06-29T17:45:26.290, type=InvoiceRefuseConsumer]
I have already created a RequestContextListener bean but I did not succeed.
Could someone tell me what might be causing this error?
Here is my code:
Module 1 - Queue consumer
#Service
public class InvoiceRefuseConsumer extends AbstractQueue implements IQueueConsumer{
#Autowired
private InvoiceRefuseService invoiceRefuseService;
#JmsListener(destination = "${amazon.sqs.queue-to-be-consumed}")
#Override
public void listener(#Payload String message) throws ApplicationException {
try {
//Convert the payload received by the queue to the InvoiceFuseParam object
InvoiceRefuseParam param = convertToPojo(message, InvoiceRefuseParam.class);
// Set the type and reason of the refused invoice
param.setType(InvoiceRefuseType.INVOICE_TREATMENT.getId());
if(param.getReasonCode().equals(InvoiceRefuseTypeOperationType.TYPE_OPERATION_INSERT.getDesc())) {
// Persist data information
invoiceRefuseService.save(param);
} else if(param.getReasonCode().equals(InvoiceRefuseTypeOperationType.TYPE_OPERATION_DELETE.getDesc())) {
// Remove refused invoice
invoiceRefuseService.delete(param.getKeyAccess(), param.getType());
}
} catch(Exception e) {
throw new ApplicationException("Error listener queue", e);
}
}
}
Module 2 - Service operations
#Service
public class InvoiceRefuseService {
/**
* automatically initiates the InvoiceRefuseCrud
*/
#Autowired
private InvoiceRefuseCrud invoiceRefuseCrud;
/**
* automatically initiates the SupplierCrud
*/
#Autowired
private SupplierCrud supplierCrud;
/**
* automatically initiates the SequenceDao
*/
#Autowired
private SequenceDao sequenceDao;
/**
* automatically initiates the InvoiceRefuseDao
*/
#Autowired
private InvoiceRefuseDao invoiceRefuseDao;
/**
* automatically initiates the OrderConsumerService
*/
#Autowired
private OrderConsumerService orderConsumerService;
/**
* automatically initiates the InvoiceOrderService
*/
#Autowired
private InvoiceOrderService invoiceOrderService;
/**
* automatically initiates the BranchWarehouseTypeDao
*/
#Autowired
private BranchWarehouseTypeDao branchWarehouseTypeDao;
/**
* Method created to delete a invoice refuse
* #param key
* #param type
* #throws ApplicationException
*/
#Transactional
public void delete(String key, int type) throws ApplicationException {
try {
// Search for the refused invoices
List<InvoiceRefuseModel> lsInvoiceRefuseModel = invoiceRefuseCrud.findBykeyAccessAndType(key, type);
if(ApplicationUtils.isEmpty(lsInvoiceRefuseModel)){
throw new FieldValidationException(getKey("key.notfound"));
}
// Remove refused invoice and cascate with the the scheduling order
invoiceRefuseCrud.deleteAll(lsInvoiceRefuseModel);
} catch (Exception e) {
throw new ApplicationException(getKey("api.delete.error"), e);
}
}
/**
* Method created to save a new invoice refuse
* #param param
* #throws ApplicationException
*/
#OneTransaction
public void save(InvoiceRefuseParam param) throws ApplicationException {
try {
for (String orderNumber : param.getOrderNumbers()) {
// Verify if the invoice refused key already exists
Optional.ofNullable(invoiceRefuseCrud.findBykeyAccessAndType(param.getKeyAccess(), param.getType()))
.filter(invoiceRefuses -> invoiceRefuses.isEmpty())
.orElseThrow(() -> new ApplicationException(getKey("invoice.alread.exists")));
// Convert to model
InvoiceRefuseModel model = convertToSaveModel(param, orderNumber);
// Save data on database
InvoiceRefuseModel result = invoiceRefuseCrud.save(model);
// Associate new refused invoice with the scheduled order
associateInvoiceRefusedToSchedulingOrder(result);
}
} catch (Exception e) {
throw new ApplicationException(getKey("api.save.error"), e);
}
}
/**
* Method creates to associate a refused invoice to the scheduling order
* #param invoiceRefuseModel
* #throws ApplicationException
*/
public void associateInvoiceRefusedToSchedulingOrder(InvoiceRefuseModel invoiceRefuseModel) throws ApplicationException{
// Search for the scheduled order
List<InvoiceOrderModel> lsInvoiceOrderModel = invoiceOrderService.findByNuOrder(invoiceRefuseModel.getNuOrder());
for (InvoiceOrderModel orderModel : lsInvoiceOrderModel) {
// Verify if its a SAP order
boolean isOrderSap = Optional
.ofNullable(branchWarehouseTypeDao.findByIdBranch(orderModel.getNuReceiverPlant()))
.filter(branch -> branch.getNaLoadPoint() != null)
.isPresent();
if (isOrderSap) {
// Update the order status
invoiceOrderService.updateStatus(orderModel);
}
}
}
/**
* Method created to convert from param to model
* #param param
* #param orderNumber
* #return InvoiceRefuseModel
* #throws ApplicationException
*/
private InvoiceRefuseModel convertToSaveModel(InvoiceRefuseParam param, String orderNumber) throws ApplicationException{
OrderParam orderParam = new OrderParam();
orderParam.getLsOrdeNumber().add(orderNumber);
// Search for SAP orders
OrderDataPojo orderSap = Optional.ofNullable(orderConsumerService.findAll(orderParam))
.filter(ordersSap -> ordersSap.getOrders().size() > 0)
.orElseThrow(() -> new ApplicationException(getKey("ordersap.notfound")));
// Convert to model
InvoiceRefuseModel model = new InvoiceRefuseModel();
model.setNuOrder(orderNumber);
model.setCdCompany(BranchMatrixType.MATRIX.getCdCompany());
model.setDsMessage(param.getReasonDescription());
model.setDtIssue(param.getIssueDate());
model.setKeyAccess(param.getKeyAccess());
model.setNuGuid(param.getGuid());
model.setNuInvoice(param.getInvoiceNumber() + param.getInvoiceSerialNumber());
model.setTsCreation(new Date());
model.setNuInvoiceSerial(param.getInvoiceSerialNumber());
model.setNuIssuerPlant(orderSap.getOrders().stream().map(o -> o.getHeader().getIssuerPlant()).findFirst().get());
model.setNuReceiverPlant(orderSap.getOrders().stream().map(o -> o.getHeader().getReceiverPlant()).findFirst().get());
model.setType(param.getType());
model.setCdInvoiceRefuseMessage(param.getReasonCode());
// Passing these fields is required for refused invoices, but they are not received for notes in treatment
if(param.getType().equals(InvoiceRefuseType.INVOICE_REFUSED.getId())) {
model.setIsEnableReturn(BooleanType.getByBool(param.getIsEnableReturn()).getId());
model.setDtRefuse(param.getRefuseDate());
}
// Search for the issuing supplier
SupplierModel supplierModelIssuer = findSupplier(param.getDocumentIdIssuer());
model.setCdSupplierIssuer(supplierModelIssuer.getCdSupplier());
// Search for the receiver supplier
SupplierModel supplierModelReceiver = findSupplier(param.getDocumentIdIssuer());
model.setCdSupplierReceiver(supplierModelReceiver.getCdSupplier());
// Set the primary key
InvoiceRefuseModelId id = new InvoiceRefuseModelId();
id.setCdInvoiceRefuse(sequenceDao.nextIntValue(SequenceName.SQ_INVOICE_REFUSE));
model.setId(id);
return model;
}
/**
* Method created to search for a supplier
* #param documentId
* #return SupplierModel
* #throws ApplicationException
*/
private SupplierModel findSupplier(String documentId) throws ApplicationException{
// Search for the supplier
SupplierModel model = supplierCrud.findTop1ByNuDocumentIdAndCdCompany(documentId, BranchMatrixType.MATRIX.getCdCompany());
if(model == null){
throw new ApplicationException(getKey("supplier.notfound"));
}
return model;
}
/**
* Method created to find a refused invoice and return the result by page
* #param param
* #param pageable
* #return Page<InvoiceRefuseModel>
* #throws ApplicationException
*/
public Page<InvoiceRefuseModel> findRefuseInvoice(InvoiceRefuseFilterParam param, Pageable pageable) throws ApplicationException {
return invoiceRefuseDao.findRefuseInvoice(param, pageable);
}
/**
* Method created to find a refused invoice and return the result by list
* #param param
* #return List<InvoiceRefuseModel>
* #throws ApplicationException
*/
public List<InvoiceRefuseModel> findRefuseInvoice(InvoiceRefuseFilterParam param) throws ApplicationException {
return invoiceRefuseDao.findRefuseInvoice(param);
}
/**
* Method created to find a refused invoice by order number and return the result by list
* #param nuOrder
* #return List<InvoiceRefuseModel>
*/
public List<InvoiceRefuseModel> findByNuOrder(String nuOrder){
return invoiceRefuseDao.findByNuOrder(nuOrder);
}
}

Mac application menu for java program that also runs on windows

I am working on a program that will work on both Windows and Mac machines. I found this link that explains how to implement the application menu on a Mac. But since it uses mac specific classes for interfaces I am not sure how to write the class so it compiles in Windows as well.
I can recommend JavaFx. The interface will look like windows on windows and like mac on mac. You can use normal java for everything that works on every machine. In addition, the Jfx Scene builder can help you with designing the application.
I should have googled a little further. Found this class on a old google group. Just had to extend it to include Preferences.
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class OSXAdapter implements InvocationHandler {
private OSXQuitListener _quitListener;
private OSXAboutListener _aboutListener;
private OSXPreferenceListener _perferenceListener;
/**
* creates this adapter, only does stuff when we're on a mac, if it's unable to
* register the quit adapter, then we throw an exception.
*
* #throws ClassNotFoundException
* #throws SecurityException
* #throws NoSuchMethodException
* #throws IllegalArgumentException
* #throws IllegalAccessException
* #throws InvocationTargetException
*/
#SuppressWarnings({ "rawtypes", "unchecked" })
public OSXAdapter() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
// get's the os name
String vers = System.getProperty("os.name").toLowerCase();
// only attempt to the do the following if we're on a mac
if (vers.indexOf("mac") != -1) {
Class quitHandlerClass = Class.forName("com.apple.mrj.MRJQuitHandler");
Class aboutHandlerClass = Class.forName("com.apple.mrj.MRJAboutHandler");
Class prefHandlerClass = Class.forName("com.apple.mrj.MRJPrefsHandler");
Class mrjapputilsClass = Class.forName("com.apple.mrj.MRJApplicationUtils");
Object methodHandler = Proxy.newProxyInstance(quitHandlerClass.getClassLoader(), new Class[] { quitHandlerClass, aboutHandlerClass, prefHandlerClass }, this);
Method appUtilsObj = mrjapputilsClass.getMethod("registerQuitHandler", new Class[] { quitHandlerClass });
appUtilsObj.invoke(null, new Object[] { methodHandler });
appUtilsObj = mrjapputilsClass.getMethod("registerAboutHandler", new Class[] { aboutHandlerClass });
appUtilsObj.invoke(null, new Object[] { methodHandler });
appUtilsObj = mrjapputilsClass.getMethod("registerPrefsHandler", new Class[] { prefHandlerClass });
appUtilsObj.invoke(null, new Object[] { methodHandler });
}
}
/**
* registers an about dialog. When the os x system fires the event which
* triggers an about class
*
* #param listener
*/
public void setAboutListener(OSXAboutListener listener) {
_aboutListener = listener;
}
/**
* registers an preference listener. When the os x fires the preference event this will be
* fired.
*
* #param listener
*/
public void setPerferenceListener(OSXPreferenceListener listener) {
_perferenceListener = listener;
}
/**
* register an quit listener. When the os x fires the quit event this will be
* fired.
*
* #param listener
*/
public void setQuitListener(OSXQuitListener listener) {
_quitListener = listener;
}
/**
* #see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
* java.lang.reflect.Method, java.lang.Object[])
*/
public Object invoke(Object proxy, Method meth, Object[] args) throws Throwable {
if (meth.getName().equals("handleQuit")) {
if (null != _quitListener) {
_quitListener.handleQuit();
}
} else if (meth.getName().equals("handleAbout")) {
if (null != _aboutListener) {
_aboutListener.handleAbout();
}
} else if (meth.getName().equals("handlePrefs")) {
if (null != _perferenceListener) {
_perferenceListener.handlePrefs();
}
}
return null;
}
/**
* listener which listens to the about event from the os x
* system
*
* #author Chris Shorrock
*/
public interface OSXAboutListener {
/**
* handles the about display event.
*/
public void handleAbout();
}
/**
* this listener is fired when the os x system quits
*
* #author Chris Shorrock
*/
public interface OSXQuitListener {
/**
* this method is called when os x tells this application
* to quit.
*/
public void handleQuit();
}
/**
* this listener is fired when the os x system fires preferences
*
* #author Chris Shorrock
*/
public interface OSXPreferenceListener {
/**
* this method is called when os x tells this application
* to open preferences.
*/
public void handlePrefs();
}
}

Logging the PID in log4j2 without using thread context

I need to include the PID in my log4js logs. I see many examples which use the thread context. However, these need to be set on each individual thread created. I am constrained against doing this.
I need a solution that, either, does not use the thread context, or, can set the PID on all thread contexts, for any thread that may be created, from any arbitrary class.
Please create a feature request on the Log4j2 issue tracker to make this a built-in feature.
For now, you can create a custom plugin. See code below. This will allow you to specify %pid in the pattern layout (similar to %m for the message).
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
#Plugin(name = "ProcessIdPatternConverter", category = "Converter")
#ConverterKeys({ "pid", "processId" })
public final class ProcessIdPatternConverter extends LogEventPatternConverter {
private final String pid;
private ProcessIdPatternConverter(String[] options) {
super("Process ID", "pid");
String temp = options.length > 0 ? options[0] : "???";
try {
// likely works on most platforms
temp = ManagementFactory.getRuntimeMXBean().getName().split("#")[0];
} catch (final Exception ex) {
try {
// try a Linux-specific way
temp = new File("/proc/self").getCanonicalFile().getName();
} catch (final IOException ignoredUseDefault) {}
}
pid = temp;
}
/**
* Obtains an instance of ProcessIdPatternConverter.
*
* #param options users may specify a default like {#code %pid{NOPID} }
* #return instance of ProcessIdPatternConverter.
*/
public static ProcessIdPatternConverter newInstance(final String[] options) {
return new ProcessIdPatternConverter(options);
}
#Override
public void format(final LogEvent event, final StringBuilder toAppendTo) {
toAppendTo.append(pid);
}
}
See the manual for more details on how Log4j2 plugins work.
One way to let Log4j2 recognize your plugin is by specifying the package name of the plugin class in the packages attribute of the configuration:
<Configuration status="trace"
packages="com.myorg.mypluginpackage">
(Trace switches on Log4j2 internal debugging to help with troubleshooting.)

How do I retrieve the modified date for the file?

In my program, I am trying to get the last modified date for some items in my box folders, but I am unable to access that information.
According to the documentation for the box API and the javadoc for the java library, any of the following methods of BoxTypedObject should return the information I want:
getModifiedAt() should return a String in ISO 8601 format for the date.
getModifiedDate() should return a Date object for the date.
getValue("modified_at") should also return a String in ISO 8601 format for the date.
getExtraData("modified_at") is also a possible way, although I am not as sure of this one.
However, none of those methods has worked for me; they all just returh null.
The (vastly simplified) code that I am using to retrieve the dates is as follows, with one of the above methods substituted for the comment block:
private static void printAll(BoxFolder boxFolder){
for(BoxTypedObject file : boxFolder.getItemCollection().getEntries())
System.out.printf("[\"%1$s\" %2$s]%n",
file.getValue("name"), file./*[???]*/);
}
The other fields all return the correct values, only when I try to get the date does it fail on me.
How do I retrieve the modified date for the BoxTypedObjects?
EDIT: I have figured out one way to get it, but it is somewhat slow.
client.getFilesManager().getFile(file.getId(), null).getModifiedAt()
retrieves the date. I am still interested if there is a better way to do it, though.
Additional information (may or may not be relevant to the problem):
The authentication of the box client is handled by the following class:
import java.awt.Desktop;
import java.io.*;
import java.net.*;
import com.box.boxjavalibv2.BoxClient;
import com.box.boxjavalibv2.dao.BoxOAuthToken;
import com.box.boxjavalibv2.exceptions.*;
import com.box.boxjavalibv2.requests.requestobjects.BoxOAuthRequestObject;
import com.box.restclientv2.exceptions.BoxRestException;
/**
* This class handles the storage and use of authentication keys, to
* simplify the process of obtaining n authenticated client. This class
* will store refresh keys in a file, so that it can authenticate a client
* without needing for user intervention.
* <p>
* Copyright 2013 Mallick Mechanical, Inc.
*
* #author Anson Mansfield
*/
public class Authenticator {
/**
* Constructs an {#code Authenticator} for use obtaining
* authenticated {#Code BoxClient}s
*
* #param key The OAuth client id and application key.
* #param secret The OAuth client secret.
* #param authFile The file to be used for storing authentications
* for later use.
*/
public Authenticator(String key, String secret, File authFile){
this.key = key;
this.secret = secret;
this.authFile = authFile;
}
/**
* Constructs a new {#Code BoxClient} object, authenticates it,
* and returns it.
*/
public BoxClient getAuthenticatedClient(){
BoxClient client = new BoxClient(key,secret);
client.authenticate(getToken(client));
return client;
}
public final String host = "http://localhost";
public final int port = 4000;
public final String key, secret;
public final File authFile;
public final String url = "https://www.box.com/api/oauth2/authorize?response_type=code&client_id=";
/**
* Obtains a token that can be used to authenticate the box client,
* and stores its refresh value in a file, so it can be used later.
* #param client The client to obtain a token for.
* #return A token that can be used to authenticate the client, or
* {#code null} if one could not be obtained.
*/
private BoxOAuthToken getToken(BoxClient client){
BoxOAuthToken token = null;
try{
if((token = getOldToken(client)) != null) return token;
if((token = getNewToken(client)) != null) return token;
return token;
}finally{
writeNewToken(token);
}
}
/**
* Attempts to write a token's refresh token to a file.
* #param token The token whose refresh value is to be written.
*/
private void writeNewToken(BoxOAuthToken token) {
if(token != null)
try(BufferedWriter out = new BufferedWriter(new FileWriter(authFile))){
out.write(token.getRefreshToken());
}catch(IOException ex){
System.out.println("couldn't update new token");
}
}
/**
* Reads the last session's refresh token from a file and attempts
* to get a new authentication token with it.
* #param client The client for which the authentication token is for.
* #return The token obtained from the refresh, or {#code null} if one
* could not be obtained.
*/
private BoxOAuthToken getOldToken(BoxClient client) {
System.out.println("attempting to use old token");
BoxOAuthToken token = null;
try(BufferedReader in = new BufferedReader(new FileReader(authFile))){
token = client.getOAuthManager().refreshOAuth(
BoxOAuthRequestObject.refreshOAuthRequestObject(
in.readLine(), key, secret
));
System.out.println("refreshed old token");
}catch(IOException ex){
System.out.println("couldn't read old token");
} catch(BoxRestException | BoxServerException | AuthFatalFailureException ex){
System.out.println("couldn't refresh old token");
}
return token;
}
/**
* Connects to the OAuth server and gets a new authentication token.
* #param client The client to get a token for.
* #return The new token obtained from the server, or {#code null} if one could not be obtained.
*/
private BoxOAuthToken getNewToken(BoxClient client) {
System.out.println("attempting to get new token");
BoxOAuthToken token = null;
try {
Desktop.getDesktop().browse(java.net.URI.create(url + key));
token = client.getOAuthManager().createOAuth(
BoxOAuthRequestObject.createOAuthRequestObject(getCode(), key, secret, host + port)
);
} catch (BoxRestException | BoxServerException | AuthFatalFailureException | IOException ex) {
ex.printStackTrace();
return null;
}
return token;
}
/**
* This listens on the configured port for the code included in the callback.
* It also deploys a script on the receiving socket to close the browser tab navigating to it.
* #return The authentication code to generate a token with.
*/
private String getCode(){
try (ServerSocket serverSocket = new ServerSocket(port);
Socket socket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());){
out.println("<script type=\"text/javascript\">");
out.println( "window.open('', '_self', '');");
out.println( "window.close();");
out.println("</script>"); //Close the tab
while (true){
String code = "";
code = in.readLine ();
System.out.println(code);
String match = "code";
int loc = code.indexOf(match);
if( loc >0 ) {
int httpstr = code.indexOf("HTTP")-1;
code = code.substring(code.indexOf(match), httpstr);
String parts[] = code.split("=");
code=parts[1];
return code;
} else {
// It doesn't have a code
}
}
} catch (IOException | NullPointerException e) {
return "";
}
}
}
The actual class that will be getting the modified field (not yet finished, though):
import java.io.File;
import java.util.Scanner;
import com.box.boxjavalibv2.BoxClient;
import com.box.boxjavalibv2.dao.BoxFolder;
import com.box.boxjavalibv2.dao.BoxTypedObject;
/**
* Copyright 2013 Mallick Mechanical, Inc.
*
* #author Anson Mansfield
*/
public class BoxStuff {
static BoxClient client;
public void main(String ... args) throws Exception {
client = new Authenticator(args[0], args[1], new File(args[2]))
.getAuthenticatedClient();
userSelectFolder("Select the project folder");
}
private static BoxFolder userSelectFolder(String prompt) throws Exception{
Scanner kbd;
if(System.console()!=null)
kbd = new Scanner(System.console().reader());
else
kbd = new Scanner(System.in);
String line = "";
System.out.println();
System.out.println(prompt);
System.out.println("(leave prompt blank to select folder)");
BoxFolder current = client.getFoldersManager().getFolder("0", null);
printAll(current);
System.out.print("select>");
while(!(line = kbd.nextLine()).isEmpty()){
BoxFolder next = select(current, Integer.parseInt(line));
if(next != null) current = next;
printAll(current);
System.out.print("select>");
}
return current;
}
private static void printAll(BoxFolder boxFolder){
int idx=0;
System.out.println(" 0:[parent folder]");
for(BoxTypedObject file : boxFolder
.getItemCollection()
.getEntries()){
if(file.getType().equals("folder")){
System.out.printf("%1$3d:[%2$-32s %3$-6s %4$-9s]%n",
++idx, format((String) file.getValue("name"),30), file.getType(), file.getId());
} else {
System.out.printf(" [%1$-32s %2$-6s %3$-9s Edit:%4$s]%n",
format((String) file.getValue("name"),32), file.getType(), file.getId(), file.getExtraData("modified_at"));
}
}
}
private static String format(CharSequence source, int length){
StringBuilder b = new StringBuilder(length);
b.append('"');
if(source.length() > 30)
b.append(source.subSequence(0, 29)).append('~');
else
b.append(String.format("%1$-30s",source));
b.append('"');
return b.toString();
}
private static BoxFolder select(BoxFolder boxFolder, int i) throws Exception{
int idx=0;
for(BoxTypedObject file : boxFolder.getItemCollection().getEntries()){
if(file.getType().equals("folder") && ++idx == i){
return client.getFoldersManager().getFolder(file.getId(), null);
}
}
if(idx==0){
if(boxFolder.getParent() == null)
return client.getFoldersManager().getFolder("0", null);
else
return client.getFoldersManager().getFolder(boxFolder.getParent().getId(), null);
}else{
System.out.println("Selection is out of range!");
return boxFolder;
}
}
}
If anyone else wants to use these classes for something, just ask me. It is probably OK (they are a mechanical contractor, not a software company), I just need to clear it with my boss (This code does still belong to the company).
This is actually a little tricky. The api call to get folder items by default only return children items with some default fields, they don't include fields like modified_at. However if you supply extra fields parameters you should be able to get them.
Here is what you can do when using the getFolderItems method(this is also in the readme in github):
BoxFolderRequestObject requestObj =
BoxFolderRequestObject.getFolderItemsRequestObject(30, 20)
.addField(BoxFolder.FIELD_NAME)
.addField(BoxFolder.FIELD_MODIFIED_AT);
BoxCollection collection =
boxClient.getFoldersManager().getFolderItems(folderId, requestObj);
There is another tricky thing here though, after you supply these fields, the result children items will only contain the supplied fields(plus some basic fields), so make sure you add all the fields you want.
Here is one way I figured out to get it (that actually works):
client.getFilesManager().getFile(file.getId(), null).getModifiedAt()
This, however, is somewhat slow, so I would greatly appreciate it if someone else knows a faster solution.

Categories

Resources