From: Frank Goenninger DG1SBG
Subject: How to implement a control for "you are not allowed to call me"
Date: 
Message-ID: <87smlflvmq.fsf@stargate.de.goenninger.com>
Hi there again.

After having fixed some minor problems with my first real application
in CL I now want to control the call to a fuction.

The case:

(defclass class-a ()
  ((doesnt-matter :accessor doesnt-matter :initform nil)))

(defclass class-b ()
  ((a :accessor a :initform nil)))

(defmethod initialize-instance :after ((self class-b) &key)
  (setf (a self) (make-instance 'class-a)))

Now when a

(setq instance-of-class-b (make-instance 'class-b))

is done slot a of the new instance is bound to an instance of class-a.

This is the OK case in that the make-instance for class-b is called
from within the method initialize-instance for class-b.

How do I prevent a direct call to make-instance of class-a ? I want
to limit the make-instance call for class-a to be only valid from
within the method initialize-instance :after ((self class-b)) ...

Is there an idiom out there for that (in portable code, preferably) ?

Thx for info.

Regards,
  Frank

From: Kenny Tilton
Subject: Re: How to implement a control for "you are not allowed to call me"
Date: 
Message-ID: <vCUmb.8565$Gq.3715642@twister.nyc.rr.com>
Frank Goenninger DG1SBG wrote:

> Hi there again.
> 
> After having fixed some minor problems with my first real application
> in CL I now want to control the call to a fuction.
> 
> The case:
> 
> (defclass class-a ()
>   ((doesnt-matter :accessor doesnt-matter :initform nil)))
> 
> (defclass class-b ()
>   ((a :accessor a :initform nil)))
> 
> (defmethod initialize-instance :after ((self class-b) &key)
>   (setf (a self) (make-instance 'class-a)))
> 
> Now when a
> 
> (setq instance-of-class-b (make-instance 'class-b))
> 
> is done slot a of the new instance is bound to an instance of class-a.
> 
> This is the OK case in that the make-instance for class-b is called
> from within the method initialize-instance for class-b.
> 
> How do I prevent a direct call to make-instance of class-a ? I want
> to limit the make-instance call for class-a to be only valid from
> within the method initialize-instance :after ((self class-b)) ...
> 
> Is there an idiom out there for that (in portable code, preferably) ?
> 

I always wonder whether:

(let ((password-a (gensym)))
     (defmethod initialize-instance :before ((self class-a) &key 
password &allow-other-keys)
          (assert (eq password-a password)))

     (defmethod i-i :after ((self class-b) &key)
         (setf (a self) (make-instance 'class-a :password password-a)))

...would work.

kenny (looking forward to being shot down by Lisp Gurus <g>)

-- 
http://tilton-technology.com
What?! You are a newbie and you haven't answered my:
  http://alu.cliki.net/The%20Road%20to%20Lisp%20Survey
From: Frank Goenninger DG1SBG
Subject: Re: How to implement a control for "you are not allowed to call me"
Date: 
Message-ID: <87d6cjvjj1.fsf@stargate.de.goenninger.com>
Heh? Kenny, what are you just trying to tell me?

Ok. Let's see what I can figure out....

The possible answers to your piece of code are:

1. Obviously YES. This does work. 

2. Obviously YES. Always. So, no sense in there. And so no sense in the
   question.

3. It smells also like "NO". My interpretations:

   - "Silly thing to want to do."

     Hm. No. Not for me. Lisp is just a bit too open for "users" (other
     software developers) to crash my system by doing something in the
     kernel of the system.

   - "Hey. It just can't be done."

     Ok. Accepted. But there are ways - using some global var.
   . OTOH that wouldn't be especially secure.

     I could image something inelegant like: 

     step 1: set the name of the function currently being executed.
     step 2: in the function needing to know the caller check that
             name before setting own name.

     But there is also the call stack. Hm. Yes, using info from that
     would be highly implementation-specific. That's ok for me. But is
     this also platform-specific? From a recent thread about 
     multiple-value performance I seem to get that this is true.

Feedback highly welcome... Kenny, I'm sure using Cells would help, no?

Regards,
  Frank  
From: Kenny Tilton
Subject: Re: How to implement a control for "you are not allowed to call me"
Date: 
Message-ID: <idWmb.8862$Gq.3761646@twister.nyc.rr.com>
Frank Goenninger DG1SBG wrote:
> Heh? Kenny, what are you just trying to tell me?

<heh-heh> Exactly what I said!

This kind of thing comes up a lot, and I do wonder whether something as 
simple as using a gensym to get an object no one else can get (well, 
that is where I expect to get shot down) and then using that as a 
"password" if you will would work.

So it seems to me it should work, but there is nothing like floating 
something on c.l.l. to get an education.

I /did/ consider asking precisely what the concern was that led to the 
requirement, but hey, it's your requirement.

> Feedback highly welcome... Kenny, I'm sure using Cells would help, no?

As you well know, if Cells applied you'da heard about it. :)

Btw, you mentioned a global. Yeah, right, that's better than my i-i 
initarg nonsense:

     (let ((*password* password-a))
         (make-instance ...))

then check *password*. But the key is having the two methods defined 
with the secret phrase a private object in a lexical binding no one else 
can get at.

kenny

-- 
http://tilton-technology.com
What?! You are a newbie and you haven't answered my:
  http://alu.cliki.net/The%20Road%20to%20Lisp%20Survey
From: Kenny Tilton
Subject: Re: How to implement a control for "you are not allowed to call me"
Date: 
Message-ID: <3oWmb.8928$Gq.3766668@twister.nyc.rr.com>
Frank Goenninger DG1SBG wrote:

> Feedback highly welcome... Kenny, I'm sure using Cells would help, no?

btw, you got the wrong "broken record" dig: Where the hell is your Road 
to Lisp Survey response?

   http://alu.cliki.net/RtL%20Highlight%20Film

:)

kenny

-- 
http://tilton-technology.com
What?! You are a newbie and you haven't answered my:
  http://alu.cliki.net/The%20Road%20to%20Lisp%20Survey
From: Frode Vatvedt Fjeld
Subject: Re: How to implement a control for "you are not allowed to call me"
Date: 
Message-ID: <2hptgjhh1i.fsf@vserver.cs.uit.no>
Frank Goenninger DG1SBG <····@stargate.de.goenninger.com> writes:

>    - "Silly thing to want to do."
>
>      Hm. No. Not for me. Lisp is just a bit too open for "users"
>      (other software developers) to crash my system by doing
>      something in the kernel of the system.

Have you actually experienced probliems with this? If so, why don't
you chose a name for the internal class that make it sufficiently
clear that "users" should not bother with this name. Usually, not
exporting the symbol all it takes.

If you are intent on hiding things away, you can of course make an
effort to do so. But to me it seems extremely pointless to "protect"
yourself from people who presumably have access to the source code,
the address space, and absolutely everything else.

-- 
Frode Vatvedt Fjeld
From: james anderson
Subject: Re: How to implement a control for "you are not allowed to call me"
Date: 
Message-ID: <3F9C06D3.18680E2B@setf.de>
it depends on what you really want to constrain...

Frank Goenninger DG1SBG wrote:
> 
> ...
> Now when a
> 
> (setq instance-of-class-b (make-instance 'class-b))
> 
> is done slot a of the new instance is bound to an instance of class-a.
> 
> This is the OK case in that the make-instance for class-b is called
> from within the method initialize-instance for class-b.
> 
> How do I prevent a direct call to make-instance of class-a ? I want
> to limit the make-instance call for class-a to be only valid from
> within the method initialize-instance :after ((self class-b)) ...
> 

do you want to preclude use of the symbol class-a to designate a class in any
other context, or is it the application of make-instance to that symbol, or to
the class designated, or do you need to prevent specialization of the class
and/or instantiation of specialized classes, or ...

?
From: Frank Goenninger DG1SBG
Subject: Re: How to implement a control for "you are not allowed to call me"
Date: 
Message-ID: <87he1vvl46.fsf@stargate.de.goenninger.com>
Yeah, I almost "knew" I have not made my question precise enough. So let's
sort that out... 

james anderson <··············@setf.de> writes:

> it depends on what you really want to constrain...
>
> Frank Goenninger DG1SBG wrote:
>> 
>> ...
>> Now when a
>> 
>> (setq instance-of-class-b (make-instance 'class-b))
>> 
>> is done slot a of the new instance is bound to an instance of class-a.
>> 
>> This is the OK case in that the make-instance for class-b is called
>> from within the method initialize-instance for class-b.
>> 
>> How do I prevent a direct call to make-instance of class-a ? I want
>> to limit the make-instance call for class-a to be only valid from
>> within the method initialize-instance :after ((self class-b)) ...
>> 
>
> do you want to preclude use of the symbol class-a to designate a class in any
> other context, 

No.

> or is it the application of make-instance to that symbol, 

No.

> or to the class designated, 

YES ! This should only be possible with said method 
intitialize-instance :after ((self class-b)).


> or do you need to prevent specialization of the class

No.

> and/or instantiation of specialized classes, or ...

No. Nothing else. So far, at least.

>
> ?

So: Is there a solution to this ?

Thx again.

Frank
From: james anderson
Subject: Re: How to implement a control for "you are not allowed to call me"
Date: 
Message-ID: <3F9C1FBD.484361B7@setf.de>
Frank Goenninger DG1SBG wrote:
> 
> ...
> >> ...
> >> Now when a
> >>
> >> (setq instance-of-class-b (make-instance 'class-b))
> >>
> >> is done slot a of the new instance is bound to an instance of class-a.
> >>
> >> This is the OK case in that the make-instance for class-b is called
> >> from within the method initialize-instance for class-b.
> >>
> >> How do I prevent a direct call to make-instance of class-a ? I want
> >> to limit the make-instance call for class-a to be only valid from
> >> within the method initialize-instance :after ((self class-b)) ...
> >>
> >
> > do you want to preclude ... the application of make-instance ...
> > to the class designated,
> 
> YES ! This should only be possible with said method
> intitialize-instance :after ((self class-b)).
> 

despite assurances to the contrary, it is surprising that it should not be
necessary to also preclude the cases of allocate-instance, change-class, etc.
on the other hand, if one goes too far, persistence would be complicated.

in any case, as a variation on the earlier suggestion, one might also consider
modifying and checking the dynamic context.

(defclass locked-class (standard-class)
  ())

(defclass class-a ()
  ()
  (:metaclass locked-class))

(let ((lock (gensym)))
  (defmethod allocate-instance :before ((class locked-class) &key &allow-other-keys)
    (assert (boundp lock)))
  (defmethod initialize-instance :after ((self class-b) &key)
    (progv (list lock) (list self)
      (setf (a self) (make-instance 'class-a)))))

...
From: Frank Goenninger DG1SBG
Subject: Re: How to implement a control for "you are not allowed to call me"
Date: 
Message-ID: <87n0bn68az.fsf@stargate.de.goenninger.com>
Thx James. This looks flexible enough.

Frank
From: Barry Margolin
Subject: Re: How to implement a control for "you are not allowed to call me"
Date: 
Message-ID: <d2bnb.234$lK3.126@news.level3.com>
In article <··············@stargate.de.goenninger.com>,
Frank Goenninger DG1SBG  <······@darc.de> wrote:
>How do I prevent a direct call to make-instance of class-a ? I want
>to limit the make-instance call for class-a to be only valid from
>within the method initialize-instance :after ((self class-b)) ...

(defparameter *inside-b* nil)

(defmethod initialize-instance :around ((self class-b) ...)
  (let ((*inside-b* t))
    (call-next-method)))

(defmethod initialize-instance :before ((self class-a) ...)
  (unless *inside-b*
    (error "CLASS-A objects may only be created from CLASS-B")))

-- 
Barry Margolin, ··············@level3.com
Level(3), Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Frank Goenninger DG1SBG
Subject: Re: How to implement a control for "you are not allowed to call me"
Date: 
Message-ID: <877k2qh4rg.fsf@stargate.de.goenninger.com>
Barry,

this one's really nice - and simple. THX ! (Now that I've seen this I 
wonder why it didn't come to my mind ;-))

Regards,
  Frank
From: james anderson
Subject: Re: How to implement a control for "you are not allowed to call me"
Date: 
Message-ID: <3F9D638D.472E4284@setf.de>
the peanut gallery is still waiting to hear why one would really need to do this.

Frank Goenninger DG1SBG wrote:
> 
> Barry,
> 
> this one's really nice - and simple. THX ! (Now that I've seen this I
> wonder why it didn't come to my mind ;-))
> 
> Regards,
>   Frank

...
From: Frank Goenninger DG1SBG
Subject: OT: Why ! WAS: Re: Row to implement a control for "you are not allowed to call me"
Date: 
Message-ID: <878yn5ztje.fsf_-_@stargate.de.goenninger.com>
james anderson <··············@setf.de> writes:

> the peanut gallery is still waiting to hear why one would really need to do this.
>

So, here you go (attention: This going to be boring, useless, off-topic, 
and therefore should not be read by anyone not really being interested).

Ok, now that I warned everybody I want to give a short summary of why I 
think I have to "protect" certain functionality from being called from 
anywhere but from "allowed" "places".

In the Real World there is an area called Product Development in almost 
every manufacturing company. Along the product development process
a multitude of different things have to be managed:

* requirements
* features of a product
* documents (specifications, test results, ... you name it)
* parts
* product structures
* bills of material
* designs
* tasks
* actions
* workflows
* processes and process steps
* object states
* classes, definable by the customer
* timeouts in workflows
* projects
* users
* groups
* access rights
* interfaces
* collaboration along the design chain across company boundaries
* ...

(yes, this is a mix of business objects and application objects)

Today, there is a class of applications available called 

Product Data Management Systems.

Typical software vendors include:

- Agile Software (http://www.agilesoft.com)
- PTC (http://www.ptc.com/appserver/it/icm/cda/icm01_list.jsp?group=201&num=1&show=y&keyword=37)
- MatrixOne (http.//www.matrixone.com)
- SAP (http://www.sap.com/plm)
- EDS (http://www.eds.com/products/plm/teamcenter/)

to name just the major players.

All those systems (and I have to deal with them on a daily basis) are
based on the idea that you have to (more or less heavily) adapt them
to the customer's needs. This does not only mean doing some configurations
but also to extend the data model, the GUI, the business logics, ...

As those adaptions require changes down to the heart of those 
applications it requires significant effort to make them stable
again. And, of course, their Java, C, ABAP, ...

Typical "customization" timeframes are 3 to 9 months! Customers
are currently hesitating to give money to only get back value
after such a long period. 

Another fact is that those apps are running 24x7 ! No downtime
allowed. (Well, just two days a year, normally).

With that in mind I try do achieve the following:

- build a core set of functionality
- secure that core set such that no matter what any sw developer
  does this remains stable
- customization timeframe should be down to 4 to 6 weeks
- web enabled, but also a "fat client" should be there
- DB backend, preferably Oracle
- maintainability during production use
- have fun


This is why I was looking for means to achieve to limit the usability
and changeability of certain functionality in my app.

OK?  (Hey I warned you it will be boring...)

Regards,
  Frank
From: james anderson
Subject: Re: OT: Why ! WAS: Re: Row to implement a control for "you are  notallowed to call me"
Date: 
Message-ID: <3F9E303F.1781F823@setf.de>
Frank Goenninger DG1SBG wrote:
> 
> james anderson <··············@setf.de> writes:
> 
> > the peanut gallery is still waiting to hear why one would really need to do this.
> >
> 
> So, here you go (attention: This going to be boring, useless, off-topic,
> and therefore should not be read by anyone not really being interested).
> 
> [description of real world product development]
> 
> All those systems [must be] adapt[ed] to the customer's needs.
> Typical "customization" timeframes are 3 to 9 months!
> ...
> With that in mind I try do achieve the following:
> 
> - build a core set of functionality
> - secure that core set such that no matter what any sw developer
>   does this remains stable
> - customization timeframe should be down to 4 to 6 weeks
> ....

with the proviso, that, short of hardware support for security (eg. multics
rings, drm-enabled hardware) there is nothing to keep the industrious
application developer from calling out through ffi, getting a pointer to the
heap and "optimizing" things, it may be fruitful to reflect on lisp from the
following perspective.

lisp was developed to implement programs which made inferences about symbolic
expressions by operating on models for those expressions. this capability
remains very much at the heart of lisp and lisp development environments, even
if it does not appear prominently in delivered applications.

the various responses to the original post illustrated some of the ways to
take advantage of this based on an application's runtime state. in addition to
that approach, short of implementing a programming language for the domain,
one can consider that things like read, load, and compile make inferences
about how a program should behave based on assertions implicit in the printed
representation for symbols, in the arrangements of symbols in various
top-level definitions, such as defclass, defun, defmethod, and in individual
operators in the program's forms.

from this point of view, in order to limit a program's effects, in addition to
constraining its dynamic state, one can constrain the symbols it can name and
the relations of those symbols in the program. one of the other responses
pointed to the simplest way to do this: with the package system. one designs a
set of functions, classes, etc which operate together "correctly" and exports
the names of those objects only. thus the suggestion that the symbol class-a
remain internal. one can even  unintern any symbols which name things -
functions, classes, slots, ..., to which an application should not have
access. which approach suggests either uninterning the symbol class-a, or
arranging to define the class and its operations in such a way that its name
is never interned.

by similar means it is possible to impose constraints on operators such that
they can appear in certain lexical relations only. for example that database
access operators are all expressed with macros which are permitted to appear
in locking forms only.

again, a lot depends on what these libraries actually do and what interface
they need to offer, but perhaps this perspective gives you some ideas about
what one could do.

...
From: Frank Goenninger DG1SBG
Subject: Re: OT: Why ! WAS: Re: Row to implement a control for "you are  notallowed to call me"
Date: 
Message-ID: <87ekwxmw91.fsf@stargate.de.goenninger.com>
James,

thank you for the in-depth reminder of Lisp's original intent and
the insight in various possibilities of limiting access to "private" 
symbols.

I learned a lot on how to think about and on how to look at application 
domain problems the Lisp way.

Well, I am still in the early design stages so it was/is a very fruitful
discussion! I am again amazed that this thread started as a "looking for
Lisp idiom" and now grew up to an in-depth discussion of how to look at
application requirements in a new way capitalizing on Lisp's features.
 
(Also, please don't look too close to my previous post - it had numerous 
typos as well as some strange English wording as I recognized. Hm, it seems 
it was a bit too early in the day to write the article ;-) ).

Again: Thank you all very much so far. Please, all, keep going. I already 
saved the thread to my personal knowledge base for later reference..

Regards,
  Frank
From: Paolo Amoroso
Subject: Re: OT: Why ! WAS: Re: Row to implement a control for "you are not allowed to call me"
Date: 
Message-ID: <87ad7le3e8.fsf@plato.moon.paoloamoroso.it>
Frank Goenninger writes:

> Typical "customization" timeframes are 3 to 9 months! Customers
[...]
> With that in mind I try do achieve the following:
[...]
> - customization timeframe should be down to 4 to 6 weeks
[...]
> This is why I was looking for means to achieve to limit the usability
> and changeability of certain functionality in my app.

If you do this in Lisp, and no confidentiality issues are involved,
you might consider adding an entry to the industrial use and/or
success stories page at:

  http://alu.cliki.net

Kenny: here is a deal for you. If I help you with letting Lisp novices
know about the RtL survey, can you help me with mine on
industrial/research use and success stories?


> OK?  (Hey I warned you it will be boring...)

Nice try, but you didn't succeed :)


Paolo
-- 
Why Lisp?... http://alu.cliki.net/RtL%20Highlight%20Film
From: Kenny Tilton
Subject: Re: OT: Why ! WAS: Re: Row to implement a control for "you are not allowed to call me"
Date: 
Message-ID: <aCxnb.14667$Gq.4829289@twister.nyc.rr.com>
Paolo Amoroso wrote:
> Kenny: here is a deal for you. If I help you with letting Lisp novices
> know about the RtL survey, can you help me with mine on
> industrial/research use and success stories?

I am cannot be bought!

kenny

-- 
http://tilton-technology.com

Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film

Your Project Here! http://alu.cliki.net/Industry%20Application